旗下导航:搜·么
当前位置:网站首页 > .Net教程 > 正文

直接挪用vs反射挪用实例教程【C#.Net教程】,直接,问题,性能,反射

作者:搜教程发布时间:2019-11-27分类:.Net教程浏览:29评论:0


导读:  很多人都说运用反射会有机能题目,那究竟会比直接挪用慢若干呢,下面就来测试一下。直接挪用vs反射挪用下面就来写个demo来考证下直接挪用和反射挪用的机能差别,代码以下...
  很多人都说运用反射会有机能题目,那究竟会比直接挪用慢若干呢,下面就来测试一下。

直接挪用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.Expression<TDelegate>表达式树的类,与直接挪用举行对照,代码以下:

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 Func<object, 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 Func<object, 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         List<Expression> parameterExpressions = new List<Expression>();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             Expression<Action<object, object[]>> lambda = Expression.Lambda<Action<object, object[]>>(methodCall, instanceParameter, parametersParameter);45             Action<object, 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             Expression<Func<object, object[], object>> lambda = Expression.Lambda<Func<object, object[], object>>(castMethodCall, instanceParameter, parametersParameter);56             return lambda.Compile();57         }58     }

除了运用linq的表达式树生成Delegate的要领外,另有比方,CodeDom生成代码并动态编译,或许运用Emit来直接编写IL的要领来进步反射的机能,然则相对来说,上面这个要领是最简朴的。

至此,全部反射的总结就完成了!

参考文章

要领的直接挪用,反射挪用与……Lambda表达式挪用

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

二、什么是反射、反射能够做些什么

以上就是直接挪用vs反射挪用实例教程的细致内容,更多请关注ki4网别的相干文章!

标签:直接问题性能反射


欢迎 发表评论: