我有很多关于stackoverflow和msdn的帖子,并尝试了他们的解决方案,但我仍然无法让它工作,所以我希望任何人都可以帮助我。非常感谢你
首先我没有添加
MethodInfo mi = instance.GetType().GetMethod(sMethodName, myBindingFlags);
Delegate del = Delegate.CreateDelegate(typeof(ErrorEventHandler), null, mi);
直接致电
ei.AddEventHandler(instance, handler);
然后错误是
类型对象' xxxxErrorEventHandler'无法转换为类型 ' xxxxErrorEventHandler'
然后我按照下面的一些帖子修改我的代码,然后在CreateDelegate
时引发错误DLL:
public class ErrorEventArgs : EventArgs
{
public string ErrorMsg;
}
public interface IClassA
{
bool Run();
}
public class ClassA : IClassA
{
public delegate void ErrorEventHandler(object sender, ErrorEventArgs data);
public event ErrorEventHandler OnErrorHandler;
public void OnError(object sender, ErrorEventArgs data)
{
if (OnErrorHandler != null)
{
OnErrorHandler(this, data);
}
}
public bool Run()
{
// do something inside DLL
ErrorEventArgs data = new ErrorEventArgs();
data.ErrorMsg = "Hello World";
OnError(this, data)
}
}
EXE:
public delegate void ErrorEventHandler(object sender, ErrorEventArgs data);
void main()
{
Assembly assembly = Assembly.LoadFile("myDLL.dll");
Type[] types = assembly.GetTypes();
for (int i = 0; i < types.Length; i++)
{
Type type = assembly.GetType(types[i].FullName);
if (type.GetInterface("myDLL.IClassA") != null)
{
object obj = Activator.CreateInstance(type);
if (obj != null)
{
MethodInfo methodInfo = obj.GetType().GetMethod("Run");
ErrorEventHandler handler = foo;
BindingFlags myBindingFlags = BindingFlags.Instance | BindingFlags.Public;
EventInfo ei = instance.GetType().GetEvent("OnErrorHandler", myBindingFlags);
MethodInfo mi = instance.GetType().GetMethod("Run", myBindingFlags);
*// System.ArgumentException raised here
// Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type.*
Delegate del = Delegate.CreateDelegate(typeof(ErrorEventHandler), null, mi);
ei.AddEventHandler(instance, del);
bool Result = methodInfo.Invoke(instance, null);
}
}
}
public void foo(object sender, ErrorEventArgs data)
{
Console.WriteLine("In Foo!");
}
}
回复1楼
嗨汉斯,非常感谢您的回答,我按照您的建议修改我的代码。如果回调函数声明如此
private static void Callback(string msg)
并且在ClassA事件中也声明如此
public delegate void ErrorEventHandler(string msg);
public event ErrorEventHandler OnErrorHandler;
public void OnError1(string msg)
{
if (OnErrorHandler != null)
{
OnErrorHandler(msg);
}
}
工作正常,但如果在之前声明它
private static void Callback(object sender, ErrorEventArgs data)
出现错误&#34;无法绑定到目标方法,因为其签名或安全透明度与委托类型的方法不兼容。&#34;运行时
Delegate del = Delegate.CreateDelegate(ei.EventHandlerType, null, mycallback);
你知道为什么,顺便说一下真的非常感谢你的帮助。
如果修改后的代码在EXE端出现错误:
.......
BindingFlags myBindingFlags = BindingFlags.Instance | BindingFlags.Public;
EventInfo ei = instance.GetType().GetEvent("OnErrorHandler", myBindingFlags);
MethodInfo mi = instance.GetType().GetMethod(sMethodName, myBindingFlags);
var mycallback = typeof(ModuleManager).GetMethod("Callback", BindingFlags.Static | BindingFlags.NonPublic);
Delegate del = Delegate.CreateDelegate(ei.EventHandlerType, null, mycallback);
ei.AddEventHandler(instance, del);
.......
private static void Callback(object sender, ErrorEventArgs data)
{
Console.WriteLine("In Callback!");
}
答案 0 :(得分:2)
您的程序有两个名为ErrorEventHandler的委托类型。一个在上部片段中声明,另一个在下部片段中声明。它们具有不同的名称,甚至可能不在同一名称空间中,但这实际上并不重要。
CLR断然拒绝考虑两个相同的委托类型,即使它们的声明是相同的。它不会烧掉额外的CPU周期来使用反射本身来检查它们是否匹配,代表应该是快速的,并且检查兼容性并不便宜。类型转换是编译器的工作。所以它只接受完全匹配,你的反射代码需要创建一个ClassA.ErrorEventHandler类型的委托。当然你不知道它的类型,但它很容易获得。它是EventInfo.EventHandlerType。
代码中的第二个问题是委托目标,即引发事件时运行的方法。您现在传递ClassA.Run(),当然这是不正确的。您需要传递自己的方法,该方法与委托兼容。它看起来像这样:
private static void Callback(object sender, object data) {
// etc...
}
并相应地修改反射代码:
object obj = Activator.CreateInstance(type);
BindingFlags myBindingFlags = BindingFlags.Instance | BindingFlags.Public;
// Find the event and its type
EventInfo ei = obj.GetType().GetEvent("OnErrorHandler", myBindingFlags);
var delegateType = ei.EventHandlerType;
// Use our own event handler
var mycallback = typeof(Program).GetMethod("Callback", BindingFlags.Static | BindingFlags.NonPublic);
Delegate del = Delegate.CreateDelegate(delegateType, null, mycallback);
ei.AddEventHandler(obj, del);
// Call the Run method
MethodInfo methodInfo = obj.GetType().GetMethod("Run");
bool Result = (bool)methodInfo.Invoke(obj, null);
请注意,Callback事件处理程序使用 object 作为第二个参数类型。哪个好,它与不可见的ErrorEventArgs类型兼容。如果需要获取传递对象的值,则还需要在回调中使用Reflection。