Impossible de se connecter à la méthode cible lors de la création de delegates pour les propriétés

Essayer de créer deux dictionnaires de delegates émis pour améliorer les performances lors de la récupération / définition dynamic des valeurs des propriétés

Code:

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())); 

Cependant, j’obtiens l’exception suivante:

Impossible de se connecter à la méthode cible car sa signature ou sa transparence de sécurité n’est pas compatible avec celle du type délégué.

D’après ce que j’ai lu, cela sera dû aux propriétés de type static / indexed / value, la collection Properties ne contient aucune propriété statique ou indexée, mais j’ai toutefois besoin de cette fonctionnalité pour les propriétés de type valeur telles que int et double .

Comment créer les getters / setters dont j’ai besoin tout en gardant mon code abstrait et en évitant les génériques?

Ok a fini par trouver ma réponse à cette question: Problème de performance MethodInfo.Invoke

Plus précisément cet article: Faire voler la reflection et explorer les delegates

Voici le texte du code que j’ai fini avec:

 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)); } } 

Les delegates générés semblent en moyenne être 80% plus rapides que l’utilisation de la reflection, je suis donc heureux du résultat!

J’avais la même erreur. J’ai utilisé API Expressions pour résoudre ce problème.

Remarque: la méthode à référencer est

  • pas générique.
  • est statique.

Le nom du délégué est Formula et sa signature est la suivante

 public delegate float Formula(Dictionary cr, List> allr); 
  1. Get MethodInfo qui doit être référencé en tant que délégué

     Assembly assembly = results.ComstackdAssembly; var generatedType = assembly.GetType("First.NewClass"); var generatedMethod = generatedType.GetMethod("FormulaMethod"); 
  2. Préparez les arguments du délégué en tant qu’expression de paramètre. Argument 1: Dictionary Argument 2: List>

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

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

  3. Génère la méthode finale Appelez Expression et renvoyez un délégué.

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