I have walkthru much post of stackoverflow and msdn and tried their solution , but I still cannot get it works, so I hope anyone can help me out . Thank you very much
First I havent added
MethodInfo mi = instance.GetType().GetMethod(sMethodName, myBindingFlags);
Delegate del = Delegate.CreateDelegate(typeof(ErrorEventHandler), null, mi);
directly call
ei.AddEventHandler(instance, handler);
then the error is
Object of type 'xxxxErrorEventHandler' cannot be converted to type 'xxxxErrorEventHandler'.
Then I follow some post modify my code as below, then raise the error when 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!");
}
}
reply to floor 1
Hi Hans, Thanks a lot for your answer, I following your advise to modify my code. If the Callback function declare like this
private static void Callback(string msg)
and inside ClassA event also declare like this
public delegate void ErrorEventHandler(string msg);
public event ErrorEventHandler OnErrorHandler;
public void OnError1(string msg)
{
if (OnErrorHandler != null)
{
OnErrorHandler(msg);
}
}
that works fine, but if declare it like before
private static void Callback(object sender, ErrorEventArgs data)
it comes up error " Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type." when run
Delegate del = Delegate.CreateDelegate(ei.EventHandlerType, null, mycallback);
Do you know why , by the way really really thanks for your help.
error if the modified code at EXE side like:
.......
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!");
}
Your program has two delegate types named ErrorEventHandler. One declared in the upper snippet, another declared in the lower snippet. They have distinct names and probably don't even live in the same namespace, but that doesn't actually matter.
The CLR categorically refuses to consider two delegate types identical, even if their declaration is the same. It will not burn the extra CPU cycles to use reflection itself to check if they match, delegates are supposed to be fast and there's nothing cheap about checking compatibility. Type conversion is a compiler's job. So it will only accept an exact match, your reflection code needs to create a delegate of type ClassA.ErrorEventHandler. Of course you can't know the type, it is readily available however. It is EventInfo.EventHandlerType.
A second problem in your code is the delegate target, the method that runs when the event is raised. You now pass ClassA.Run(), that is not correct of course. You need to pass your own method, one that's compatible with the delegate. It could look like this:
And modify the reflection code accordingly:
Note that the Callback event handler used object as the second argument type. Which is fine, it is compatible with the invisible ErrorEventArgs type. If you need to obtain the values of the passed object then you need to use Reflection in the callback as well.