在为属性创建委托时无法绑定到目标方法

尝试创建两个发出的委托字典,以便在动态获取/设置属性值时提高性能。

码:

Properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance) .Where(p => p.CanRead && !p.GetIndexParameters().Any()) .AsEnumerable(); PropertyGetters = Properties.ToDictionary(p => p.Name, p => (Func)Delegate.CreateDelegate(typeof(Func), p.GetGetMethod())); PropertySetters = Properties.Where(p => p.GetSetMethod() != null) .ToDictionary(p => p.Name, p => (Action)Delegate.CreateDelegate(typeof(Action), p.GetSetMethod())); 

但是我得到以下exception:

无法绑定到目标方法,因为其签名或安全透明性与委托类型的签名或安全透明性不兼容。

从我所看到的,这将由静态/索引/值类型属性引起, Properties集合不包含静态或索引属性,但我确实需要它来处理值类型属性,如intdouble

如何在保持代码抽象和避免generics的同时创建我需要的getter / setter?

好的,最终从这个问题中找到了答案: MethodInfo.Invoke性能问题

更具体地说,这篇文章: 反思飞行和探索代表

以下是我最终得到的代码的主旨:

 public class Helper { private IDictionary> PropertyGetters { get; set; } private IDictionary> PropertySetters { get; set; } public static Func CreateGetter(PropertyInfo property) { if (property == null) throw new ArgumentNullException("property"); var getter = property.GetGetMethod(); if (getter == null) throw new ArgumentException("The specified property does not have a public accessor."); var genericMethod = typeof(Helper).GetMethod("CreateGetterGeneric"); MethodInfo genericHelper = genericMethod.MakeGenericMethod(property.DeclaringType, property.PropertyType); return (Func)genericHelper.Invoke(null, new object[] { getter }); } public static Func CreateGetterGeneric(MethodInfo getter) where T : class { Func getterTypedDelegate = (Func)Delegate.CreateDelegate(typeof(Func), getter); Func getterDelegate = (Func)((object instance) => getterTypedDelegate((T)instance)); return getterDelegate; } public static Action CreateSetter(PropertyInfo property) { if (property == null) throw new ArgumentNullException("property"); var setter = property.GetSetMethod(); if (setter == null) throw new ArgumentException("The specified property does not have a public setter."); var genericMethod = typeof(Helper).GetMethod("CreateSetterGeneric"); MethodInfo genericHelper = genericMethod.MakeGenericMethod(property.DeclaringType, property.PropertyType); return (Action)genericHelper.Invoke(null, new object[] { setter }); } public static Action CreateSetterGeneric(MethodInfo setter) where T : class { Action setterTypedDelegate = (Action)Delegate.CreateDelegate(typeof(Action), setter); Action setterDelegate = (Action)((object instance, object value) => { setterTypedDelegate((T)instance, (V)value); }); return setterDelegate; } public Helper(Type type) { var Properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance) .Where(p => p.CanRead && !p.GetIndexParameters().Any()).AsEnumerable(); PropertyGetters = Properties.ToDictionary(p => p.Name, p => CreateGetter(p)); PropertySetters = Properties.Where(p => p.GetSetMethod() != null) .ToDictionary(p => p.Name, p => CreateSetter(p)); } } 

生成的代表平均看起来比使用reflection快80%,所以我对结果很满意!

我得到了同样的错误。 我使用Expressions API来解决此问题。

注意:要引用的方法是

  • 不通用。
  • 是静态的。

委托名称为Formula,其签名如下

 public delegate float Formula(Dictionary cr, List> allr); 
  1. 获取将被引用为Delegate的MethodInfo

     Assembly assembly = results.CompiledAssembly; var generatedType = assembly.GetType("First.NewClass"); var generatedMethod = generatedType.GetMethod("FormulaMethod"); 
  2. 准备代理作为参数表达式的参数。 参数1: Dictionary参数2: List>

     var arg1Expression = Expression.Parameter(typeof(Dictionary)); 

    var arg2Expression = Expression.Parameter(typeof(List>));

  3. 生成最终方法Call Expression并返回Delegate。

     var methodCall = Expression.Call(generatedMethod, arg1Expression, arg2Expression); return Expression.Lambda  (methodCall, arg1Expression, arg2Expression).Compile();