首页后端开发ASP.NET直接调用vs反射调用实例教程

直接调用vs反射调用实例教程

时间2024-01-30 09:50:03发布访客分类ASP.NET浏览329
导读:收集整理的这篇文章主要介绍了直接调用vs反射调用实例教程,觉得挺不错的,现在分享给大家,也给大家做个参考。 很多人都说使用反射会有性能问题,那到底会比直接调用慢多少呢,下面就来测试一下。直接调用vs反射调用下面就来写个demo来验证下直接...
收集整理的这篇文章主要介绍了直接调用vs反射调用实例教程,觉得挺不错的,现在分享给大家,也给大家做个参考。  很多人都说使用反射会有性能问题,那到底会比直接调用慢多少呢,下面就来测试一下。

直接调用vs反射调用

下面就来写个demo来验证下直接调用和反射调用的性能差异,代码如下:

 1 namespace ConsoleApplication7 2 {
 3     class PRogram 4     {
 5         static void Main(string[] args) 6         {
     7             //比较直接调用和反射调用的性能差异 8             //7ms vs 365ms 9             int times = 1000000;
    10             VAR program = new Program();
    11             CodeTimerHelPEr.InITialize();
    12 13             CodeTimerHelper.Time("直接调用", times, () =>
14             {
    15                 program.Call();
16             }
    );
    17 18             var t = typeof(Program);
    19             var obj = Activator.Createinstance(t);
    20             CodeTimerHelper.Time("反射调用", times, () =>
21             {
    22                 t.InvokeMember("Call", BindingFlags.InvokeMethod, null, obj, null);
23             }
    );
    24 25             Console.ReadKey();
26         }
    27 28         /// summary>
    29         /// 测试方法30         /// /summary>
31         public void Call()32         {
33         }
34 35     }
36 }
    

测试结果:

从100万次调用结果来看,确实就像很多人所说的,两者在性能上具有数量级的差距。

为什么反射有性能损失

既然反射性能有损失,那具体损失在哪里呢?

1,反射是基于程序集和元数据的,在使用反射的时候,会搜索元数据,而元数据是基于字符串的,并且无法预编译,所以这一系列的操作对性能有影响。

2,大量的装箱拆箱也对性能有影响。由于我们对目标类型是未知的,而且向方法传递的参数通常是object类型的,所以会有大量的装箱和拆箱。

反射性能优化方案

我们已经知道使用反射有性能问题,但是有些场景下又不得不使用反射技术,所以要想办法优化反射性能。

这里就引用老赵公开的System.Linq.ExPressions.ExpressionTDelegate> 表达式树的类,与直接调用进行对比,代码如下:

1 //3,基于表达式树2 var methodInfo = t.GetMethod("Call");
    3 var executor = new DynamicMethodExecutor(methodInfo);
    4 CodeTimerHelper.Time("Dynamic executor", times, () =>
5 {
    6     executor.Execute(obj, null);
7 }
    );
    

测试结果:

哇,同样的100万次调用,使用DynamicMethodExecutor调用跟直接调用的性能相差无几。

附DynamicMethodExecutor的封装代码:

 1 /// summary>
     2 ///  3 /// /summary>
 4 public class DynamicMethodExecutor 5 {
     6     private Funcobject, object[], object>
     m_execute;
 7  8     public DynamicMethodExecutor(MethodInfo methodInfo) 9     {
    10         this.m_execute = this.GetExecuteDelegate(methodInfo);
11     }
12 13     public object Execute(object instance, object[] parameters)14     {
    15         return this.m_execute(instance, parameters);
16     }
    17 18     private Funcobject, object[], object>
 GetExecuteDelegate(MethodInfo methodInfo)19     {
    20         // parameters to execute21         ParameterExpression instanceParameter = Expression.Parameter(typeof(object), "instance");
    22         ParameterExpression parametersParameter = Expression.Parameter(typeof(object[]), "parameters");
    23 24         // build parameter list25         ListExpression>
     parameterExpressions = new ListExpression>
    ();
    26         ParameterInfo[] paramInfos = methodInfo.GetParameters();
    27         for (int i = 0;
     i  paramInfos.Length;
 i++)28         {
    29             // (Ti)parameters[i]30             BinaryExpression valueObj = Expression.ArrayIndex(parametersParameter, Expression.Constant(i));
    31             UnaryExpression valueCast = Expression.Convert(valueObj, paramInfos[i].ParameterType);
    32             parameterExpressions.Add(valueCast);
33         }
    34 35         // non-instance for static method, or ((TInstance)instance)36         Expression instanceCast = methodInfo.IsStatic ? null : Expression.Convert(instanceParameter, methodInfo.ReflectedType);
    37 38         // static invoke or ((TInstance)instance).Method39         MethodCallExpression methodCall = Expression.Call(instanceCast, methodInfo, parameterExpressions);
40 41         // ((TInstance)instance).Method((T0)parameters[0], (T1)parameters[1], ...)42         if (methodCall.Type == typeof(void))43         {
    44             ExpressionActionobject, object[]>
    >
     lambda = Expression.LambdaActionobject, object[]>
    >
    (methodCall, instanceParameter, parametersParameter);
    45             Actionobject, object[]>
     execute = lambda.COMpile();
    46             return (instance, parameters) =>
47             {
    48                 execute(instance, parameters);
    49                 return null;
50             }
    ;
51         }
52         else53         {
    54             UnaryExpression castMethodCall = Expression.Convert(methodCall, typeof(object));
    55             ExpressionFuncobject, object[], object>
    >
     lambda = Expression.LambdaFuncobject, object[], object>
    >
    (castMethodCall, instanceParameter, parametersParameter);
    56             return lambda.Compile();
57         }
58     }
    

除了使用linq的表达式树生成Delegate的方法外,还有比如,CodeDom生成代码并动态编译,或者使用Emit来直接编写IL的方法来提高反射的性能,但是相对来说,上面这个方法是最简单的。

至此,整个反射的总结就完成了!

参考文章

方法的直接调用,反射调用与……Lambda表达式调用

C#基础知识梳理系列十五:反射

二、什么是反射、反射可以做些什么

以上就是直接调用vs反射调用实例教程的详细内容,更多请关注其它相关文章!

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!

性能直接问题

若转载请注明出处: 直接调用vs反射调用实例教程
本文地址: https://pptw.com/jishu/592362.html
浅析Angular中两种类型的Form表单 怎么在EXECL文件中同时导入数据和插入图片?

游客 回复需填写必要信息