Ce que je veux réellement faire est quelque chose comme ceci (je réalise que ce n’est pas un code valide):
// Attach the event. try { EventInfo e = mappings[name]; (e.EventHandlerType) handler = (sender, raw) => { AutoWrapEventArgs args = raw as AutoWrapEventArgs; func.Call(this, args.GetParameters()); }; e.AddEventHandler(this, handler); } ...
Maintenant, je sais que le e.EventHandlerType sera toujours dérivé de EventHandler . Cependant, je ne peux pas simplement faire:
EventHandler handler = (sender, raw) => { AutoWrapEventArgs args = raw as AutoWrapEventArgs; func.Call(this, args.GetParameters()); }; e.AddEventHandler(this, handler);
Comme .NET se plaint qu’aucune conversion n’est applicable de EventHandler à EventHandler lorsque AddEventHandler est appelé. C’est le message exact:
Object of type 'System.EventHandler`1[IronJS.AutoWrapObject+AutoWrapEventArgs]' cannot be converted to type 'System.EventHandler`1[Node.net.Modules.Streams.NodeStream+DataEventArgs]'.
J’ai également essayé d’utiliser Invoke pour utiliser de manière dynamic le constructeur de e.EventHandlerType, mais il n’existe aucun moyen de passer la définition du délégué à la liste de parameters de Invoke () (car il n’y a pas de conversion de délégué en object).
Est-il possible d’utiliser la reflection pour résoudre ce problème?
Bingo! L’astuce consiste à obtenir une référence au constructeur pour le type de délégué, puis de l’invoquer à l’aide des parameters suivants:
Le code qui en résulte ressemble à ceci (t dans ce cas, l’argument générique fourni à EventHandler <> pendant l’héritage):
Type t = e.EventHandler.GetGenericArguments()[0]; Delegate handler = (Delegate) typeof(EventHandler<>) .MakeGenericType(t) .GetConstructors()[0] .Invoke(new object[] { backend.Target, backend.Method.MethodHandle.GetFunctionPointer() });
Vous pouvez ensuite utiliser le délégué pour l’événement en ajoutant comme suit:
e.AddEventHandler(this, handler);
Vous pouvez utiliser Delegate.CreateDelegate
pour atteindre votre objective comme ceci:
public void RegisterHandler(ssortingng name) { EventInfo e = mappings[name]; EventHandler handler = (s, raw) => { func.Call(this, raw.GetParameters()); }; e.AddEventHandler(this, Delegate.CreateDelegate(e.EventHandlerType, null, handler.Method)); }