如何在无法访问EventArgs类型时使用反射添加事件处理程序?

时间:2014-02-03 18:41:28

标签: c# .net events reflection 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类型时,有什么方法可以处理事件吗?

1 个答案:

答案 0 :(得分:1)

实际上,我想通了。

我改变了

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

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

并使Program课程公开,一切正常。