جيل الحدث الديناميكي في C # باستخدام DynamicMethod وILGenerator

StackOverflow https://stackoverflow.com/questions/674728

  •  21-08-2019
  •  | 
  •  

سؤال

وأنا بحاجة لتوليد معالج حدث على أساس كائن EventInfo في وقت واستدعاء أسلوب ضمن ذلك معالج الحدث. شيء كما يلي:

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

وأنا بحاجة للمساعدة في توليد رمز IL بالنسبة للجزء علق.

هل كانت مفيدة؟

المحلول

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

تعديل : في حان للتفكير في ذلك، إذا كان كل الأحداث تتبع (المرسل، وسائط) النمط، حتى أنك لا تحتاج إلى القيام به الفوضى مع 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)) ;
}

نصائح أخرى

وانا التخمين كنت تريد أن تجعل من مندوب من MethodInfo هذا الحدث الخاص بك ...

وإذا كان الأمر كذلك، هنا هي المقالة يصف كيف للذهاب حول هذا الموضوع. وأوضح رموز IL المطلوبة في تلك المادة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top