从数据库(文件,类和方法名称).为了方便,加快和减少使用反射我想要一个缓存….
遵循使用:
MethodInfo.Invoke
没有什么表现(Reflection Performance – Create Delegate (Properties C#))
我想翻译任何对方法的调用.我想到了会这样工作的东西:
public static T Create<T>(Type type,string methodname) // orpublic 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,任何参数像我一样?
我在想,如果有这样的话呢?
https://codereview.stackexchange.com/questions/1070/generic-advanced-delegate-createdelegate-using-expression-trees
但是我会有更多的参数(在动作或函数中),这个参数(第一个参数)要执行一个对象.
这可能吗?
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);
参数规则:
>如果传递的方法是一个实例方法,生成的委托的第一个参数将接受包含方法本身的对象的实例.所有其他参数将被传递给该方法.>如果传递的方法是一个静态方法,那么生成的委托的所有参数将被传递给该方法.>缺少参数将传递默认值.>额外的参数将被丢弃.
总结以上是内存溢出为你收集整理的为任何方法创建Func或Action(在c#中使用反射)全部内容,希望文章能够帮你解决为任何方法创建Func或Action(在c#中使用反射)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)