2009-03-23 12 views
1

J'ai besoin de générer un gestionnaire d'événements basé sur un objet EventInfo en exécution et d'appeler une méthode dans ce gestionnaire d'événements. Quelque chose comme le suivant:Génération d'événements dynamiques en C# avec DynamicMethod et ILGenerator

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

J'ai besoin d'aide pour générer le code IL pour la partie commentée.

+0

Avez-vous une question? – leppie

+0

Oui. La partie indiquée dans les commentaires (comme l'a mentionné Reed Copsey) – Khash

Répondre

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

Modifier: venez y penser, si tous vos événements suivent le modèle (expéditeur, args), vous ne même pas besoin de faire jouer avec 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)) ; 
} 
+0

Aucune des solutions proposées ne fonctionne: La première utilise le premier argument de la méthode générée et non l'actionData de la méthode RegisterAction. Le second essaie de générer un événement avec la mauvaise signature: ActionData ne doit pas être l'un des paramètres d'une méthode avec (objet, T) – Khash

+0

Le premier paramètre de la méthode statique sera lié à l'objet cible par le constructeur délégué , donc ça devrait marcher (utiliser la technique dans mon code), même si j'avoue que je n'ai pas compilé et exécuté ce code particulier. –

+0

Lisez ceci http://msdn.microsoft.com/en-us/library/74x8f551.aspx –

1

Je devine que vous voulez faire un délégué de la MethodInfo de votre événement ...

Si oui, here is an article décrivant comment s'y prendre. Les codes IL requis sont expliqués dans cet article.

Questions connexes