I have the following code in one assembly:

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

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

    class MyArgs : EventArgs
    {
    }
}

and the following code in another assembly:

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

However, I get the following exception at Delegate.CreateDelegate: Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type.

The types in the first assembly are internal and cannot be changed, nor grant friend assembly access to the second.

I tried to dynamically create a method via the following:

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

However, I get the following exception at MethodBase.Invoke: Attempt by method 'DynamicClass.MyHandlerImpl(System.Object, MyLibrary.MyArgs)' to access type 'MyLibrary.MyArgs' failed.

Is there any way I can handle an event when I do not have access to the EventArgs type?

有帮助吗?

解决方案

Actually, I figured it out.

I changed

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

to

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

and made the Program class public and everything worked.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top