2014-02-03 2 views
1

я следующий код в одной сборке:Как добавить обработчик события, используя отражение, когда у вас нет доступа к типу EventArgs?

namespace MyLibrary 
{ 
    class InternalClass 
    { 
     public event EventHandler<MyArgs> MyEvent; 

     public void RaiseMyEvent() 
     { 
      MyEvent(this, new MyArgs()); 
     } 
    } 

    class MyArgs : EventArgs 
    { 
    } 
} 

и следующий код в другой сборке:

namespace MyApp 
{ 
    class Program 
    { 
     static void Main() 
     { 
      var assembly = Assembly.LoadFrom(@"C:\path\to\MyLibrary.dll"); 
      var types = assembly.GetTypes(); 
      var internalClassType = types.FirstOrDefault(t => t.FullName == "MyLibrary.InternalClass"); 
      var eventInfo = internalClassType.GetEvent("MyEvent"); 

      var internalClass = Activator.CreateInstance(internalClassType); 
      eventInfo.AddEventHandler(internalClass, 
       Delegate.CreateDelegate(eventInfo.EventHandlerType, typeof(Program), "MyHandler")); 

      internalClassType.GetMethod("RaiseMyEvent").Invoke(internalClass, new object[0]); 
     } 

     public static void MyHandler(object sender, EventArgs e) 
     { 
     } 
    } 
} 

Однако, я получаю следующее исключение в Delegate.CreateDelegate: Невозможно привязать к целевой методе потому что его подпись или прозрачность безопасности несовместимы с прозрачностью типа делегата.

Типы в первой сборке являются внутренними и не могут быть изменены, а также не позволяют доступу к сбору доступа к второму.

Я пытался динамически создать метод с помощью следующего:

namespace MyApp 
{ 
    class Program 
    { 
     static void Main() 
     { 
      var assembly = Assembly.LoadFrom(@"C:\path\to\MyLibrary.dll"); 
      var types = assembly.GetTypes(); 
      var internalClassType = types.FirstOrDefault(t => t.FullName == "MyLibrary.InternalClass"); 
      var myArgsType = types.FirstOrDefault(t => t.FullName == "MyLibrary.MyArgs"); 
      var eventInfo = internalClassType.GetEvent("MyEvent"); 

      var methodInfo = typeof(Program).GetMethod("MyHandler"); 
      var method = new DynamicMethod("MyHandlerImpl", null, new[] { typeof(object), myArgsType }); 
      var generator = method.GetILGenerator(); 
      generator.Emit(OpCodes.Ldarg_0); 
      generator.Emit(OpCodes.Ldarg_1); 
      generator.Emit(OpCodes.Call, methodInfo); 
      generator.Emit(OpCodes.Ret); 

      var internalClass = Activator.CreateInstance(internalClassType); 
      eventInfo.AddEventHandler(internalClass, method.CreateDelegate(eventInfo.EventHandlerType)); 

      internalClassType.GetMethod("RaiseMyEvent").Invoke(internalClass, new object[0]); 
     } 

     public static void MyHandler(object sender, EventArgs e) 
     { 
     } 
    } 
} 

Однако, я получаю следующее исключение в MethodBase.Invoke: Попытка методом 'DynamicClass.MyHandlerImpl (System.Object, MyLibrary.MyArgs)' для доступа к типу «MyLibrary.MyArgs» не удалось.

Есть ли способ обработать событие, когда у меня нет доступа к типу EventArgs?

+0

Я узнал что-то новое. Спасибо! – LunicLynx

ответ

1

Собственно, я понял.

Я изменил

var method = new DynamicMethod("MyHandlerImpl", null, new[] { typeof(object), myArgsType }); 

в

var method = new DynamicMethod("MyHandlerImpl", null, new[] { typeof(object), typeof(EventArgs) }); 

и сделал Program класс общественности и все работало.