I have some issues creating the correct delegates for some methods of my classes. There is a base class and a derived class, both have a method protected object GetValue (EnumPID)
, but EnumPID
is defined separately in both classes. So in general both functions can be distinguished from each other.
Now I tried to create delegates to these functions usingDelegate.CreateDelegate (Type, object, string)
,
because new <delegate-name>(function)
does not work as the function
is not public.
The failure is that both delegates created by Delegate.CreateDelegate()
point to the same function, which is the one from the derived class.
To simplify it, here's the test class. I found out, that it's not necessary to use inheritance, it can be reproduced with 2 different enums in the same class as well:
public class CClass
{
public delegate void DelegatePrint1 (Enum1 i_en1);
public delegate void DelegatePrint2 (Enum2 i_en2);
public delegate void DelegatePrint3 (Enum3 i_en3);
public enum Enum1 { a = 1, b = 2 }
public enum Enum2 { a = 99 }
public enum Enum3 { z = 100 }
public void Print (Enum1 i_en1) { Console.WriteLine (i_en1.ToString () + "=" + (int)i_en1); }
public void Print (Enum2 i_en2) { Console.WriteLine (i_en2.ToString () + "=" + (int)i_en2); }
public void Print (Enum3 i_en3) { Console.WriteLine (i_en3.ToString () + "=" + (int)i_en3); }
}
private static void Main ()
{
string sMethod_Print = "Print";
var oClass = new CClass ();
var delPrint1 = (CClass.DelegatePrint1)Delegate.CreateDelegate (typeof (CClass.DelegatePrint1), oClass, sMethod_Print);
var delPrint2 = (CClass.DelegatePrint2)Delegate.CreateDelegate (typeof (CClass.DelegatePrint2), oClass, sMethod_Print);
var delPrint3 = (CClass.DelegatePrint3)Delegate.CreateDelegate (typeof (CClass.DelegatePrint3), oClass, sMethod_Print);
delPrint1 (CClass.Enum1.a);
delPrint1 (CClass.Enum1.b);
delPrint2 (CClass.Enum2.a);
delPrint3 (CClass.Enum3.z);
}
The expected output is
a=1
b=2
a=99
z=100
The actual output is
1=1
2=2
99=99
z=100
because all delegates call the Print(Enum3)
.
My questions:
1) How can I create the correct delegate? (I've already found out, see my own answer below).
2) Why does CreateDelegate (Type, object, string)
create a delegate of the wrong function? Is the given Type not sufficient to determine the correct one?
Obviously the constructor of a delegate is much smarter than the Delegate.CreateDelegate()
function, becausevar del1 = new CClass.DelegatePrint1 (oClass.Print);
creates the correct delegate, but this only works if the function is public.
The solution is: Instead ofDelegate.CreateDelegate (Type, object, string)
you must useDelegate.CreateDelegate (Type, object, MethodInfo)
with the MethodInfo being var oMethod1 = typeof (CClass).GetMethod ("Print", new Type[] { typeof (CClass.Enum1) });
In this way the correct overload of Print
is selected.
As to why this is necessary (which is my 2nd question), I don't have an answer. I checked out the .net source of CreateDelegate()
at https://referencesource.microsoft.com/#mscorlib/system/delegate.cs,2b489eed284b305b , but I am not quite sure about how it works, because it calls external methods MulticastDelegate InternalAlloc(RuntimeType type)
and bool BindToMethodName(Object target, RuntimeType methodType, String method, DelegateBindingFlags flags)
. I guess that either the type information is not fully preserved by InternalAlloc
, or BindToMethodName
takes the Enum
as an int
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.