推荐一个快速反射调用的类

使用传统的.net反射机制,调用类的方法时,在调用频率大的情况下,会感觉速度很慢。最近浏览卢彦的博客时,找到一个他改进后的反射调用类。试用以后感觉效率明显提高,特推荐给大家。作者重新实现了,反射调用方法,但是调用接口和.net原有方法一致。而且调用时抛出的异常为所调用类的实际异常,不像传统方式返回为包装异常。
文章来源:
http://www.codeproject.com/csharp/FastMethodInvoker.asp

快速反射调用类

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Reflection.Emit;

namespace FastMethodInvoker
ExpandedBlockStart.gifContractedBlock.gif
{
    
class FastInvoke
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
public delegate object FastInvokeHandler(object target, object[] paramters);

        
static object InvokeMethod(FastInvokeHandler invoke, object target, params object[] paramters)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
return invoke(null, paramters);
        }


        
public static FastInvokeHandler GetMethodInvoker(MethodInfo methodInfo)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
ExpandedSubBlockStart.gifContractedSubBlock.gif            DynamicMethod dynamicMethod 
= new DynamicMethod(string.Empty, typeof(object), new Type[] typeof(object), typeof(object[]) }, methodInfo.DeclaringType.Module);
            ILGenerator il 
= dynamicMethod.GetILGenerator();
            ParameterInfo[] ps 
= methodInfo.GetParameters();
            Type[] paramTypes 
= new Type[ps.Length];
            
for (int i = 0; i < paramTypes.Length; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
if (ps[i].ParameterType.IsByRef)
                    paramTypes[i] 
= ps[i].ParameterType.GetElementType();
                
else
                    paramTypes[i] 
= ps[i].ParameterType;
            }

            LocalBuilder[] locals 
= new LocalBuilder[paramTypes.Length];

            
for (int i = 0; i < paramTypes.Length; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                locals[i] 
= il.DeclareLocal(paramTypes[i], true);
            }

            
for (int i = 0; i < paramTypes.Length; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                il.Emit(OpCodes.Ldarg_1);
                EmitFastInt(il, i);
                il.Emit(OpCodes.Ldelem_Ref);
                EmitCastToReference(il, paramTypes[i]);
                il.Emit(OpCodes.Stloc, locals[i]);
            }

            
if (!methodInfo.IsStatic)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                il.Emit(OpCodes.Ldarg_0);
            }

            
for (int i = 0; i < paramTypes.Length; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
if (ps[i].ParameterType.IsByRef)
                    il.Emit(OpCodes.Ldloca_S, locals[i]);
                
else
                    il.Emit(OpCodes.Ldloc, locals[i]);
            }

            
if (methodInfo.IsStatic)
                il.EmitCall(OpCodes.Call, methodInfo, 
null);
            
else
                il.EmitCall(OpCodes.Callvirt, methodInfo, 
null);
            
if (methodInfo.ReturnType == typeof(void))
                il.Emit(OpCodes.Ldnull);
            
else
                EmitBoxIfNeeded(il, methodInfo.ReturnType);

            
for (int i = 0; i < paramTypes.Length; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
if (ps[i].ParameterType.IsByRef)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
{
                    il.Emit(OpCodes.Ldarg_1);
                    EmitFastInt(il, i);
                    il.Emit(OpCodes.Ldloc, locals[i]);
                    
if (locals[i].LocalType.IsValueType)
                        il.Emit(OpCodes.Box, locals[i].LocalType);
                    il.Emit(OpCodes.Stelem_Ref);
                }

            }


            il.Emit(OpCodes.Ret);
            FastInvokeHandler invoder 
= (FastInvokeHandler)dynamicMethod.CreateDelegate(typeof(FastInvokeHandler));
            
return invoder;
        }


        
private static void EmitCastToReference(ILGenerator il, System.Type type)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
if (type.IsValueType)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                il.Emit(OpCodes.Unbox_Any, type);
            }

            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                il.Emit(OpCodes.Castclass, type);
            }

        }


        
private static void EmitBoxIfNeeded(ILGenerator il, System.Type type)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
if (type.IsValueType)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                il.Emit(OpCodes.Box, type);
            }

        }


        
private static void EmitFastInt(ILGenerator il, int value)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
switch (value)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
case -1:
                    il.Emit(OpCodes.Ldc_I4_M1);
                    
return;
                
case 0:
                    il.Emit(OpCodes.Ldc_I4_0);
                    
return;
                
case 1:
                    il.Emit(OpCodes.Ldc_I4_1);
                    
return;
                
case 2:
                    il.Emit(OpCodes.Ldc_I4_2);
                    
return;
                
case 3:
                    il.Emit(OpCodes.Ldc_I4_3);
                    
return;
                
case 4:
                    il.Emit(OpCodes.Ldc_I4_4);
                    
return;
                
case 5:
                    il.Emit(OpCodes.Ldc_I4_5);
                    
return;
                
case 6:
                    il.Emit(OpCodes.Ldc_I4_6);
                    
return;
                
case 7:
                    il.Emit(OpCodes.Ldc_I4_7);
                    
return;
                
case 8:
                    il.Emit(OpCodes.Ldc_I4_8);
                    
return;
            }


            
if (value > -129 && value < 128)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                il.Emit(OpCodes.Ldc_I4_S, (SByte)value);
            }

            
else
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                il.Emit(OpCodes.Ldc_I4, value);
            }

        }

    }

}


效果测试程序

using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;

namespace FastMethodInvoker
ExpandedBlockStart.gifContractedBlock.gif
{
    
class Program
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
static void Main(string[] args)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{

            Type t 
= typeof(Person);
            MethodInfo methodInfo 
= t.GetMethod("Say");
            Person person 
= new Person();
            
string word = "hello";
            Person p 
= null;
ExpandedSubBlockStart.gifContractedSubBlock.gif            
object[] param = new object[] { word, p, 3 };
            
int TestTimes = 100000//测试次数,可自行调节看效果

ContractedSubBlock.gifExpandedSubBlockStart.gif            
传统方式反射#region 传统方式反射
            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                Stopwatch watch 
= new Stopwatch();
                watch.Start();
                
for (int i = 0; i < TestTimes; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
{
                    methodInfo.Invoke(person, param);
                }

                watch.Stop();
                Console.WriteLine(TestTimes.ToString() 
+ " times invoked by Reflection: " + watch.ElapsedMilliseconds + "ms");
            }

            
catch (System.Exception ex)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                Console.WriteLine(
"传统方式反射 直接错误:" + ex.Message);
                Console.WriteLine(
"传统方式反射 内部错误:" + ex.InnerException.Message);
            }

            
#endregion


ContractedSubBlock.gifExpandedSubBlockStart.gif            
快速反射#region 快速反射
            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                Stopwatch watch1 
= new Stopwatch();
                FastInvoke.FastInvokeHandler fastInvoker 
= FastInvoke.GetMethodInvoker(methodInfo);
                watch1.Start();
                
for (int i = 0; i < TestTimes; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
{
                    fastInvoker(person, param);
                }

                watch1.Stop();
                Console.WriteLine(TestTimes.ToString() 
+ " times invoked by FastInvoke: " + watch1.ElapsedMilliseconds + "ms");
            }

            
catch (System.Exception ex)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                Console.WriteLine(
"快速反射 错误:" + ex.Message);
            }

            
#endregion


ContractedSubBlock.gifExpandedSubBlockStart.gif            
直接调用#region 直接调用
            
try
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                Stopwatch watch2 
= new Stopwatch();
                watch2.Start();
                
for (int i = 0; i < TestTimes; i++)
ExpandedSubBlockStart.gifContractedSubBlock.gif                
{
                    person.Say(
ref word, out p, 3);
                }

                watch2.Stop();
                Console.WriteLine(TestTimes.ToString() 
+ " times invoked by DirectCall: " + watch2.ElapsedMilliseconds + "ms");
            }

            
catch (System.Exception ex)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                Console.WriteLine(
"直接调用 错误:" + ex.Message);
            }

            
#endregion

            
            Console.ReadLine();
        }

    }


    
public class Person
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        
public void Say(ref string word, out Person p, int avi)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            word 
= "ttt" + avi.ToString();
            p 
= new Person();

            
//throw new System.Exception("出错了哦");
        }

    }

}

转载于:https://www.cnblogs.com/haoliansheng/archive/2009/06/01/1493909.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/276513.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

面试官问:JS的继承

原文作者若川&#xff0c;掘金链接&#xff1a;https://juejin.im/post/5c433e216fb9a049c15f841b写于2019年2月20日&#xff0c;现在发到公众号声明原创&#xff0c;之前被《前端大全》公众号等转载阅读量超1w&#xff0c;知乎掘金等累计阅读量超过1w。导读&#xff1a;文章主…

qt 快速按行读取文件_这是知识点之Linux下分割文件并保留文件头

点击上方"开发者的花花世界"&#xff0c;选择"设为星标"技术干货不定时送达&#xff01;这是一个知识点方便快捷的给结构化数据文件分割大小并保留文件的表头&#xff0c;几十个G的结构化文件不仅阅读编辑麻烦&#xff0c;而且使用受限&#xff0c;因此高效…

mono 调用windows webService

1. 实现linux mono Develop中调用windows 中的webService l linux 与 windows 在一个局域网的网段中 l windows 的IIs中发布webService 2. windows 中的设置 l webService 的代码 using System; using System.Collections.Generic; using System.Linq; using S…

学习 sentry 源码整体架构,打造属于自己的前端异常监控SDK

前言这是学习源码整体架构第四篇。整体架构这词语好像有点大&#xff0c;姑且就算是源码整体结构吧&#xff0c;主要就是学习是代码整体结构&#xff0c;不深究其他不是主线的具体函数的实现。文章学习的是打包整合后的代码&#xff0c;不是实际仓库中的拆分的代码。其余三篇分…

绑定dictionary 给定关键字不再字典中_VBA代码集锦-利用字典做两列数据的对比并对齐...

源数据&#xff1a;代码&#xff1a;Sub 对比()Dim arr, brr, crrDim i, j, n, lastrowA, lastrowB As Integer建立字典对象Set d CreateObject("scripting.dictionary")获取数据区域最后一行的行数lastrowA Sheets("对比对齐两列数据").Cells(Rows.Coun…

前端使用puppeteer 爬虫生成《React.js 小书》PDF并合并

前端也可以爬虫&#xff0c;写于2018年08月29日&#xff0c;现在发布到微信公众号申明原创。掘金若川 本文章链接&#xff1a;https://juejin.im/post/5b86732451882542af1c80821、 puppeteer 是什么&#xff1f;puppeteer: Google 官方出品的 headless Chrome node 库puppetee…

信息安全管理与评估_计算机工程学院教师参加“信息安全管理与评估赛项”说明会...

看了就要关注我&#xff0c;喵呜~2019年3月15日下午&#xff0c;2019年陕西省高等职业院校技能大赛“信息安全管理与评估赛项说明会”在咸阳职业技术学院举行。出席本次会仪的有咸阳职业技术学院教务处长杨新宇、神州数码范永强经理、神州数码信息安全工程师高峰和各院校指导教…

haproxy概念和负载均衡

https://pan.baidu.com/s/1Sq2aJ35zrW2Xn7Th9j7oOA //软件百度网盘连接 在80.100虚拟机上 systemctl stop firewalld //关闭防火墙 setenforce 0 //关闭监控 yum install lrz* -y //安装上传软件 tar xf haproxy-1.5.15.tar.gz -C /opt/ //解压压缩包到/opt/ cd /op…

知乎问答:一年内的前端看不懂前端框架源码怎么办?

知乎问答&#xff1a;一年内的前端看不懂前端框架源码怎么办&#xff1f;以下是我的回答&#xff0c;阅读量 1000。现在转载到微信公众号中。链接&#xff1a;https://www.zhihu.com/question/350289336/answer/910970733其他回答的已经很好了。刚好最近在写学习源码整体架构系…

冷启动问题:如何构建你的机器学习组合?

作为即将告别大学的机器学习毕业狗的你&#xff0c;会不会有种迷茫的感觉&#xff1f;你知道 HR 最看重的是什么吗&#xff1f;在求职季到来之前&#xff0c;毕业狗要怎么做&#xff0c;才能受到 HR 的青睐、拿到心仪的 Offer 呢&#xff1f;负责帮助应届生找到机器学习工作的 …

JavaScript 对象所有API解析【2020版】

写于 2017年08月20日&#xff0c;虽然是2017年写的文章&#xff0c;但现在即将2020年依旧不过时&#xff0c;现在补充了2019年新增的ES10 Object.fromEntries()。发到公众号申明原创。若川顺便在此提前祝大家&#xff1a;2020年更上一层楼。近日发现有挺多人对对象基础API不熟悉…

PHP生成各种验证码和Ajax验证

转载链接&#xff1a;http://www.helloweba.com/view-blog-191.html 验证码在WEB应用中非常重要&#xff0c;通常用来防止用户恶意提交表单&#xff0c;如恶意注册和登录、论坛恶意灌水等。本文将通过实例讲解使用PHP生成各种常见的验证码包括数字验证码、数字字母验证码、中文…

若川的2019年度总结,波澜不惊

从2014年开始写年度总结至今已经六个年头了。正如孔子所说&#xff1a;逝者如斯夫&#xff0c;不舍昼夜。2019年的年度总结写得比较晚&#xff0c;都快农历新年了&#xff0c;此刻在家里继续写完这篇文章。往年基本是元旦之后几天就写完了。我的年度总结尽量写得非技术人员也能…

如何正确选择仓储物流供应商?

如何正确选择仓储物流供应商&#xff1f; 以前有做电商的朋友向我咨询过怎么去选择优质的仓储物流供应商&#xff1f;有哪些能做作为关键问题进行参考。作为一个优秀的合作伙伴是可以为客户提供超乎预期的服务的&#xff0c;上海维佳供应链服务专业提供物流外包解决仓储物流供应…

Realtime Ray Tracing RenderMan Point Cloud

这里演示的是演示的是光线与包围盒测试。在装备Winfast 8800GT 512M的台式机上可以进行每秒4.6亿次点到射线的距离计算计算&#xff0c;用于判断点是否真正的与射线相交。外部数据的填充与准备延迟依旧是GPGPU应用的一个巨大门槛。白色是命中的包围盒&#xff0c;绿色的就是射线…

如何制定有价值的目标

写于2017年07月09日23:29现在修改发布到公众号声明原创公司会制定一系列目标&#xff0c;个人也可以制定一些目标&#xff0c;有利于自我学习成长。那么看我这篇文章可以告诉你如何制定有价值的目标。会制定有价值的目标&#xff0c;绝对超越很多人。SMART原则王健林之前说定个…

清除dns缓存命令行_怎么防止移动dns劫持,防止移动dns劫持要先了解什么是dns劫持...

本人以网络技术出身&#xff0c;近两年接触CDN网络&#xff0c;处理了一些CDN方面的网络问题&#xff0c;大多数以运营商丢包&#xff0c;延迟抖动为主&#xff0c;也处理一些硬件故障&#xff0c;比如机械硬盘的读写io测试&#xff0c;内存条兼容性测试&#xff0c;服务器IPMI…

移动硬盘格式化(pc和mac共用)-菜鸟级解决方案[转]

用pc的时候买了一个320G的移动硬盘&#xff0c;从来没考虑过什么格式化的问题&#xff0c;插上就用了。 后来接触mac才发现pc和mac在移动存储设备的格式化上还是有不少冲突的。如果你的移动硬盘mac上不能修改&#xff0c;或者pc上找不到&#xff0c;那就尽情得批判万恶的资本主…

回答知乎问题:你写过什么自认为惊艳的诗?

首次整理于 2019-07-27 22:04:00&#xff0c;现在整理发布在公众号申明原创。整理了一下大学期间2012年&#xff5e;2016年发布在QQ空间&#xff0c;自己感觉写得还行的七首“诗词”。回答知乎问题&#xff1a;你写过什么自认为惊艳的诗&#xff1f;中国古诗词博大精深。小时候…

密码可逆不可逆选择_膝关节损伤不可逆!跑步要注意!

膝盖同时也是运动者最常受伤的关节。根据美国运动医学整型外科协会的报告&#xff0c;美国每年约有三百万人拉伤、挫伤、或扭伤他们的膝部&#xff0c;其中约有一半是因为运动引起的。而对于跑者而言&#xff0c;影响最大的就是我们的膝关节。换言之&#xff0c;长跑的潜在危害…