2015-12-03 7 views
0

У меня возникла проблема при попытке реализовать вызов метода, запущенного событием, которое должно быть определено во время выполнения. Я нашел этот ответ:Вызвать метод при возникновении общего события

Redirecting to a dynamic method from a generic event handler

и реализовано это решение, но я получаю исключение при вызове метода для вызова является экземпляром один, не статичны. Вот мой частичный код:

public class Operation 
{ 
    public bool EventFired 
    { 
     get { return _eventFired; } 
    } 

    private bool _eventFired = false; 

    public void Execute(object source, string EventName) 
    { 
     EventInfo eventInfo = source.GetType().GetEvent(EventName); 
     Delegate handler = null; 

     Type delegateHandler = eventInfo.EventHandlerType; 
     MethodInfo invokeMethod = delegateHandler.GetMethod("Invoke"); 
     ParameterInfo[] parms = invokeMethod.GetParameters(); 

     Type[] parmTypes = new Type[parms.Length]; 

     for (int i = 0; i < parms.Length; i++) 
      parmTypes[i] = parms[i].ParameterType; 

     DynamicMethod customMethod = new DynamicMethod 
      (
      "TempMethod", 
      invokeMethod.ReturnType, 
      parmTypes, 
      typeof (Operation).Module 
      ); 

     MethodInfo inf = typeof (Operation).GetMethod("SetFlag", BindingFlags.Instance | BindingFlags.Public); 

     ILGenerator ilgen = customMethod.GetILGenerator(); 
     ilgen.Emit(OpCodes.Ldarg_0); 
     ilgen.Emit(OpCodes.Call, inf); 
     ilgen.Emit(OpCodes.Ret); 

     //handler = _customMethod.CreateDelegate(delegateHandler);   // This works if I change SetFlag() to static 

     handler = customMethod.CreateDelegate(delegateHandler, this);  // I get an ArgumentException at this point: 
                      //Cannot bind to the target method because its signature 
                      //or security transparency is not compatible with that of the delegate type. 



     eventInfo.AddEventHandler(source, handler); 
    } 

    /// <summary>Signals that the event has been raised.</summary> 
    public void SetFlag() 
    { 
     _eventFired = true; 
    } 

} 

Я не могу найти способ, чтобы избавиться от этого исключения, код работает отлично, если я перехожу SetFlag() метода статических, но это не то, что мне нужно , Любые предложения были бы очень оценены. Спасибо заранее.

+0

Возможный дубликат (или, по крайней мере, связанный с этим вопрос): http://stackoverflow.com/questions/12865848/general-purpose-fromevent-method – Servy

ответ

0

я наконец-то удалось решить эту проблему, слегка изменив определение DynamicMethod, как описано в этом ответе:

Reference 'this' in dynamic event handler

Если добавить мой тип класса в качестве первого значения в Тип массив, который затем передается как параметр DynamicMethod, делегат правильно создан и работает с методами экземпляра!

public class Operation 
{ 
    public bool EventFired 
    { 
     get { return _eventFired; } 
    } 

    private bool _eventFired = false; 

    public void Execute(object source, string EventName) 
    { 
     EventInfo eventInfo = source.GetType().GetEvent(EventName); 
     Delegate handler = null; 

     Type delegateHandler = eventInfo.EventHandlerType; 
     MethodInfo invokeMethod = delegateHandler.GetMethod("Invoke"); 
     ParameterInfo[] parms = invokeMethod.GetParameters(); 

     Type[] parmTypes = new Type[parms.Length + 1]; 

     parmTypes[0] = this.GetType(); //First parameter is this class type. 

     for (int i = 0; i < parms.Length; i++) 
      parmTypes[i + 1] = parms[i].ParameterType; 

     DynamicMethod customMethod = new DynamicMethod 
            (
             "TempMethod", 
             invokeMethod.ReturnType, 
             parmTypes 
            ); 

     MethodInfo inf = typeof (Operation).GetMethod("SetFlag", BindingFlags.Instance | BindingFlags.Public); 

     ILGenerator ilgen = customMethod.GetILGenerator(); 
     ilgen.Emit(OpCodes.Ldarg_0); 
     ilgen.Emit(OpCodes.Call, inf); 
     ilgen.Emit(OpCodes.Ret); 

     handler = customMethod.CreateDelegate(delegateHandler, this);  

     eventInfo.AddEventHandler(source, handler); 
    } 

    /// <summary>Signals that the event has been raised.</summary> 
    public void SetFlag() 
    { 
     _eventFired = true; 
    } 

} 

 Смежные вопросы

  • Нет связанных вопросов^_^