使用Expressions调用实体的方法
Expressions如何实现反射调用实现方法类似的功能呢(并且效率比使用反射高)?下面就把方法分享给大家:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Linq.Expressions; 5 using System.Reflection; 6 using System.Text; 7 using System.Threading.Tasks; 8 9 namespace Syspetro.Core.Extensions 10 { 11 public class DynamicMethodExecutor 12 { 13 private readonly Func<object, object[], object> m_execute; 14 15 public DynamicMethodExecutor(object obj, string method) 16 { 17 MethodInfo methodInfo = obj.GetType().GetMethod(method); 18 this.m_execute = GetExecuteDelegate(methodInfo); 19 } 20 21 public DynamicMethodExecutor(MethodInfo methodInfo) 22 { 23 this.m_execute = GetExecuteDelegate(methodInfo); 24 } 25 /// <summary> 26 /// 调用方法 27 /// </summary> 28 /// <param name="instance">实体对象</param> 29 /// <param name="parameters">参数列表</param> 30 /// <returns></returns> 31 public object Execute(object instance, object[] parameters) 32 { 33 return this.m_execute(instance, parameters); 34 } 35 private static Func<object, object[], object> GetExecuteDelegate(MethodInfo methodInfo) 36 { 37 // parameters to execute 38 ParameterExpression instanceParameter = 39 Expression.Parameter(typeof(object), "instance"); 40 ParameterExpression parametersParameter = 41 Expression.Parameter(typeof(object[]), "parameters"); 42 43 // build parameter list 44 List<Expression> parameterExpressions = new List<Expression>(); 45 ParameterInfo[] paramInfos = methodInfo.GetParameters(); 46 for (int i = 0; i < paramInfos.Length; i++) 47 { 48 // (Ti)parameters[i] 49 BinaryExpression valueObj = Expression.ArrayIndex( 50 parametersParameter, Expression.Constant(i)); 51 UnaryExpression valueCast = Expression.Convert( 52 valueObj, paramInfos[i].ParameterType); 53 54 parameterExpressions.Add(valueCast); 55 } 56 57 // non-instance for static method, or ((TInstance)instance) 58 Expression instanceCast = methodInfo.IsStatic ? null : 59 Expression.Convert(instanceParameter, methodInfo.ReflectedType); 60 61 // static invoke or ((TInstance)instance).Method 62 MethodCallExpression methodCall = Expression.Call( 63 instanceCast, methodInfo, parameterExpressions); 64 65 // ((TInstance)instance).Method((T0)parameters[0], (T1)parameters[1], ...) 66 if (methodCall.Type == typeof(void)) 67 { 68 Expression<Action<object, object[]>> lambda = 69 Expression.Lambda<Action<object, object[]>>( 70 methodCall, instanceParameter, parametersParameter); 71 72 Action<object, object[]> execute = lambda.Compile(); 73 return (instance, parameters) => 74 { 75 execute(instance, parameters); 76 return null; 77 }; 78 } 79 else 80 { 81 UnaryExpression castMethodCall = Expression.Convert( 82 methodCall, typeof(object)); 83 Expression<Func<object, object[], object>> lambda = 84 Expression.Lambda<Func<object, object[], object>>( 85 castMethodCall, instanceParameter, parametersParameter); 86 87 return lambda.Compile(); 88 } 89 } 90 } 91 }
如何使用呢:
1 var service = _serviceProvider.GetService(type);//通过依赖注入实例化实体 2 3 DynamicMethodExecutor dynamicMethodRun = new DynamicMethodExecutor(service, "Run");//调用实体类的 Run()方法
4 var redata = dynamicMethodRun.Execute(service, null);//redata为方法的返回值