Un délégué ouvert est un délégué à une méthode d'instance sans la cible. Pour l'appeler, vous fournissez la cible comme premier paramètre. Ils constituent un moyen astucieux d'optimiser le code qui, sinon, utiliserait la réflexion et aurait de mauvaises performances. Pour une introduction à l'ouverture des délégués, voir this. La façon dont vous l'utiliseriez dans la pratique est d'avoir un code de réflexion coûteux pour construire ces délégués ouverts, mais alors vous seriez en mesure de les appeler très bon marché comme un simple appel de délégué. J'essaye d'écrire le code qui transformera un PropertyInfo arbitraire, en un tel délégué pour son setter. Jusqu'ici je suis venu avec ceci:Création d'un délégué ouvert performant pour un accesseur de propriété ou un getter
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace Test
{
class TestClass
{
static Action<T, object> MakeSetterDelegate<T>(PropertyInfo property)
{
MethodInfo setMethod = property.GetSetMethod();
if (setMethod != null && setMethod.GetParameters().Length == 1) //skips over nasty index properties
{
//To be able to bind to the delegate we have to create a delegate
//type like: Action<T,actualType> rather than Action<T,object>.
//We use reflection to do that
Type setterGenericType = typeof(Action<,>);
Type delegateType = setterGenericType.MakeGenericType(new Type[] { typeof(T), property.PropertyType });
var untypedDelegate = Delegate.CreateDelegate(delegateType, setMethod);
//we wrap the Action<T,actualType> delegate into an Action<T,object>
Action<T, object> setter = (instance, value) =>
{
untypedDelegate.DynamicInvoke(new object[] { instance, value });
};
return setter;
}
else
{
return null;
}
}
int TestProp
{
set
{
System.Diagnostics.Debug.WriteLine("Called set_TestProp");
}
}
static void Test()
{
PropertyInfo property = typeof(TestClass).GetProperty("TestProp");
Action<TestClass, object> setter = MakeSetterDelegate<TestClass>(property);
TestClass instance = new TestClass();
setter(instance, 5);
}
}
}
Le code semblable serait écrit pour le getter. Cela fonctionne, mais le délégué setter utilise un DynamicInvoke pour convertir d'une action <derivedType
> à l'action <object
>, qui je soupçonne mange une bonne partie de l'optimisation que je suis après. Donc les questions sont:
- Est-ce que DynamicInvoke est une réelle préoccupation?
- Y at-il de toute façon autour d'elle?
Pouvez-vous préciser votre réponse? 1-Qu'entendez-vous par "Réflexion contre un type interne générique"; 2 - Comment l'API Expression m'aiderait-elle? –
@David - Exemple d'expression ajouté. Je vais fouetter un exemple de type interne générique –
@David - et ajouté l'exemple de type générique interne –