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

标签 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 处遇到以下异常:无法绑定(bind)到目标方法,因为它的签名或安全透明度与委托(delegate)类型不兼容。

第一个程序集中的类型是内部类型,不能更改,也不能向第二个程序集授予友元程序集访问权限。

我尝试通过以下方式动态创建一个方法:

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 类型时,有什么方法可以处理事件吗?

最佳答案

其实,我想通了。

我变了

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

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

并公开了 Program 类,一切正常。

关于c# - 无法访问 EventArgs 类型时如何使用反射添加事件处理程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21535111/

相关文章:

.net - ws 在 wsHttpBinding 中实际上代表什么?

c# - 如何使用 Debugger (VS Professional 2012) 查找事件列表?

java - 如何在按下按键时锁定 KeyListener

Javascript 只接收一次 ActiveX 事件

c# - ASP.NET 命令行参数

C# WebBrowser DocumentCompleted 事件未在特定站点上触发

c# - 无法将声音文件上传到 IBM Watson 语音转文本

c# - ClickOnce安装错误

c# - 有没有办法使用 Microsoft-Graph C# 客户端库删除消息?

c# - IWebClient 将 Web 客户端接口(interface)作为依赖项注入(inject)