generazione di eventi dinamici in C # utilizzando DynamicMethod e ILGenerator
-
21-08-2019 - |
Domanda
Ho bisogno di generare un gestore di eventi in base a un oggetto EventInfo in runtime e chiamare un metodo all'interno di tale gestore di eventi. Qualcosa di simile a quanto segue:
public void RegisterAction(ActionData actionData, EventInfo eventInfo,
Control control)
{
MethodInfo methodInfo = eventInfo.EventHandlerType.GetMethod("Invoke");
List<Type> ps = new List<Type>();
foreach (ParameterInfo info in methodInfo.GetParameters())
{
ps.Add(info.ParameterType);
}
DynamicMethod method = new DynamicMethod("Adapter",
typeof (void),
ps.ToArray(),
GetType(),
true);
ILGenerator generator = method.GetILGenerator();
// Here I need to generate a method to do the following:
// ExecuteAction(actionData);
// Then I can use this runtime method as an event handler and
// bind it to the control
Delegate proxy = method.CreateDelegate(eventInfo.EventHandlerType, this);
eventInfo.AddEventHandler(control, proxy);
}
Ho bisogno di aiuto nel generare il codice IL per la parte commentato.
Soluzione
public void RegisterAction(ActionData actionData, EventInfo eventInfo,
Control control)
{
MethodInfo methodInfo = eventInfo.EventHandlerType.GetMethod("Invoke");
List<Type> ps = new List<Type>();
ps.Add (typeof (ActionData)) ;
foreach (ParameterInfo info in methodInfo.GetParameters())
{
ps.Add(info.ParameterType);
}
DynamicMethod method = new DynamicMethod("Adapter",
typeof (void),
ps.ToArray(),
GetType(),
true);
// compatible signatures for ExecuteAction
// (assuming you aren't interested in sender and eventArgs):
// static void ExecuteAction (ActionData) ;
// void ActionData.ExecuteAction () ;
MethodInfo miExecuteAction = <...> ;
ILGenerator generator = method.GetILGenerator();
generator.Emit (OpCodes.Ldarg_0) ;
generator.Emit (OpCodes.Call, miExecuteAction) ;
generator.Emit (OpCodes.Ret) ;
// if you want to pass this to ExecuteAction,
// you'll need to put it into actionData.
Delegate proxy = method.CreateDelegate(eventInfo.EventHandlerType, actionData);
eventInfo.AddEventHandler(control, proxy);
}
Modifica : venite a pensarci bene, se tutti i vostri eventi seguono le (mittente, args) modello, che non hanno nemmeno bisogno di fare confusione con SRE:
public static void Execute<T> (ActionData data, object sender, T args)
where T : EventArgs
{
ExecuteAction (data) ;
}
public void RegisterAction (ActionData actionData, EventInfo eventInfo,
Control control)
{
MethodInfo compatibleMethod = typeof (this).GetMethod ("Execute",
BindingFlags.Static | BindingFlags.Public).MakeGenericMethod (
eventInfo.EventHandlerType.GetMethod ("Invoke").GetParameters ()[1].ParameterType)) ;
eventInfo.AddEventHandler (control,
Delegate.CreateDelegate (eventInfo.EventHandlerType, actionData,
compatibleMethod)) ;
}
Altri suggerimenti
Sto indovinando si vuole fare un delegato dal MethodInfo del vostro evento ...
Se è così, ecco un articolo che descrive come per andare su questo. I codici IL richiesti sono spiegati in questo articolo.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow