我的应用程序基于设置动态加载dll
从数据库(文件,类和方法名称).为了方便,加快和减少使用反射我想要一个缓存….
从数据库(文件,类和方法名称).为了方便,加快和减少使用反射我想要一个缓存….
遵循使用:
- MethodInfo.Invoke
没有什么表现(Reflection Performance – Create Delegate (Properties C#))
我想翻译任何对方法的调用.我想到了会这样工作的东西:
- public static T Create<T>(Type type,string methodName) // or
- public static T Create<T>(MethodInfo info) // to use like this:
- var action = Create<Action<object>>(typeof(Foo),"AnySetValue");
一个要求是所有的参数,可以是对象.
我正在试图处理表达,到目前为止我有这样的事情:
- private void Sample()
- {
- var assembly = Assembly.GetAssembly(typeof(Foo));
- Type customType = assembly.GetType("Foo");
- var actionMethodInfo = customType.GetMethod("AnyMethod");
- var funcMethodInfo = customType.GetMethod("AnyGetString");
- var otherActionMethod = customType.GetMethod("AnySetValue");
- var otherFuncMethodInfo = customType.GetMethod("OtherGetString");
- var foo = Activator.CreateInstance(customType);
- var actionAccessor = (Action<object>)BuildSimpleAction(actionMethodInfo);
- actionAccessor(foo);
- var otherAction = (Action<object,object>)BuildOtherAction(otherActionMethod);
- otherAction(foo,string.Empty);
- var otherFuncAccessor = (Func<object,object>)BuildFuncAccessor(funcMethodInfo);
- otherFuncAccessor(foo);
- var funcAccessor = (Func<object,object,object>)BuildOtherFuncAccessor(otherFuncMethodInfo);
- funcAccessor(foo,string.Empty);
- }
- static Action<object> BuildSimpleAction(MethodInfo method)
- {
- var obj = Expression.Parameter(typeof(object),"o");
- Expression<Action<object>> expr =
- Expression.Lambda<Action<object>>(
- Expression.Call(
- Expression.Convert(obj,method.DeclaringType),method),obj);
- return expr.Compile();
- }
- static Func<object,object> BuildFuncAccessor(MethodInfo method)
- {
- var obj = Expression.Parameter(typeof(object),"o");
- Expression<Func<object,object>> expr =
- Expression.Lambda<Func<object,object>>(
- Expression.Convert(
- Expression.Call(
- Expression.Convert(obj,typeof(object)),obj);
- return expr.Compile();
- }
- static Func<object,object> BuildOtherFuncAccessor(MethodInfo method)
- {
- var obj = Expression.Parameter(typeof(object),"o");
- var value = Expression.Parameter(typeof(object));
- Expression<Func<object,object>>(
- Expression.Call(
- Expression.Convert(obj,method,Expression.Convert(value,method.GetParameters()[0].ParameterType)),obj,value);
- return expr.Compile();
- }
- static Action<object,object> BuildOtherAction(MethodInfo method)
- {
- var obj = Expression.Parameter(typeof(object),"o");
- var value = Expression.Parameter(typeof(object));
- Expression<Action<object,object>> expr =
- Expression.Lambda<Action<object,object>>(
- Expression.Call(
- Expression.Convert(obj,value);
- return expr.Compile();
- }
- public class Foo
- {
- public void AnyMethod() {}
- public void AnySetValue(string value) {}
- public string AnyGetString()
- { return string.Empty; }
- public string OtherGetString(string value)
- { return string.Empty; }
- }
有没有办法简化这段代码? (我相信可以创建一个只使用泛型的方法..)当你有3,4,5,任何参数像我一样?
我在想,如果有这样的话呢?
但是我会有更多的参数(在动作或函数中),这个参数(第一个参数)要执行一个对象.
这可能吗?
解决方法
我已经做了一个满足您所有要求的示例程序(我想!)
- class Program
- {
- class MyType
- {
- public MyType(int i) { this.Value = i; }
- public void SetValue(int i) { this.Value = i; }
- public void SetSumValue(int a,int b) { this.Value = a + b; }
- public int Value { get; set; }
- }
- public static void Main()
- {
- Type type = typeof(MyType);
- var mi = type.GetMethod("SetValue");
- var obj1 = new MyType(1);
- var obj2 = new MyType(2);
- var action = DelegateBuilder.BuildDelegate<Action<object,int>>(mi);
- action(obj1,3);
- action(obj2,4);
- Console.WriteLine(obj1.Value);
- Console.WriteLine(obj2.Value);
- // Sample passing a default value for the 2nd param of SetSumValue.
- var mi2 = type.GetMethod("SetSumValue");
- var action2 = DelegateBuilder.BuildDelegate<Action<object,int>>(mi2,10);
- action2(obj1,3);
- action2(obj2,4);
- Console.WriteLine(obj1.Value);
- Console.WriteLine(obj2.Value);
- // Sample without passing a default value for the 2nd param of SetSumValue.
- // It will just use the default int value that is 0.
- var action3 = DelegateBuilder.BuildDelegate<Action<object,int>>(mi2);
- action3(obj1,3);
- action3(obj2,4);
- Console.WriteLine(obj1.Value);
- Console.WriteLine(obj2.Value);
- }
- }
DelegateBuilder类:
- public class DelegateBuilder
- {
- public static T BuildDelegate<T>(MethodInfo method,params object[] missingParamValues)
- {
- var queueMissingParams = new Queue<object>(missingParamValues);
- var dgtMi = typeof(T).GetMethod("Invoke");
- var dgtRet = dgtMi.ReturnType;
- var dgtParams = dgtMi.GetParameters();
- var paramsOfDelegate = dgtParams
- .Select(tp => Expression.Parameter(tp.ParameterType,tp.Name))
- .ToArray();
- var methodParams = method.GetParameters();
- if (method.IsStatic)
- {
- var paramsToPass = methodParams
- .Select((p,i) => CreateParam(paramsOfDelegate,i,p,queueMissingParams))
- .ToArray();
- var expr = Expression.Lambda<T>(
- Expression.Call(method,paramsToPass),paramsOfDelegate);
- return expr.Compile();
- }
- else
- {
- var paramThis = Expression.Convert(paramsOfDelegate[0],method.DeclaringType);
- var paramsToPass = methodParams
- .Select((p,i + 1,queueMissingParams))
- .ToArray();
- var expr = Expression.Lambda<T>(
- Expression.Call(paramThis,paramsOfDelegate);
- return expr.Compile();
- }
- }
- private static Expression CreateParam(ParameterExpression[] paramsOfDelegate,int i,ParameterInfo callParamType,Queue<object> queueMissingParams)
- {
- if (i < paramsOfDelegate.Length)
- return Expression.Convert(paramsOfDelegate[i],callParamType.ParameterType);
- if (queueMissingParams.Count > 0)
- return Expression.Constant(queueMissingParams.Dequeue());
- if (callParamType.ParameterType.IsValueType)
- return Expression.Constant(Activator.CreateInstance(callParamType.ParameterType));
- return Expression.Constant(null);
- }
- }
怎么运行的
核心是BuildDelegate方法:
static T BuildDelegate< T>(MethodInfo方法)
> T是要创建的委托类型.
方法是要由生成的委托调用的方法的MethodInfo.
示例调用:var action = BuildDelegate< Action< object,int>>(mi);
参数规则:
>如果传递的方法是一个实例方法,生成的委托的第一个参数将接受包含方法本身的对象的实例.所有其他参数将被传递给该方法.>如果传递的方法是一个静态方法,那么生成的委托的所有参数将被传递给该方法.>缺少参数将传递默认值.>额外的参数将被丢弃.