在为类的某些方法创建正确的委托时,我遇到了一些问题。有一个基类和一个派生类,它们都具有方法protected object GetValue (EnumPID)
,但是EnumPID
在这两个类中是分别定义的。因此通常可以将两个功能区分开来。
现在,我尝试使用
创建这些函数的委托
Delegate.CreateDelegate (Type, object, string)
,
因为new <delegate-name>(function)
不公开,所以function
不起作用。
失败的原因是Delegate.CreateDelegate()
创建的两个委托都指向同一个函数,即派生类中的那个。
为简化起见,这里是测试类。我发现,不必使用继承,也可以在同一类中使用2个不同的枚举来重现它:
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);
}
预期输出为
a=1
b=2
a=99
z=100
实际输出是
1=1
2=2
99=99
z=100
因为所有代表都叫Print(Enum3)
。
我的问题:
1)如何创建正确委托? (我已经发现了,请参阅下面的答案)。
2)为什么CreateDelegate (Type, object, string)
创建错误函数的委托?给定的类型不足以确定正确的类型吗?
答案 0 :(得分:1)
显然,委托的构造函数比Delegate.CreateDelegate()
函数更聪明,因为
var del1 = new CClass.DelegatePrint1 (oClass.Print);
创建正确委托,但这仅在该函数为公共函数时有效。
解决方案是:代替
Delegate.CreateDelegate (Type, object, string)
您必须使用
Delegate.CreateDelegate (Type, object, MethodInfo)
MethodInfo为
var oMethod1 = typeof (CClass).GetMethod ("Print", new Type[] { typeof (CClass.Enum1) });
这样,可以选择正确的Print
重载。
关于为什么这是必要的(这是我的第二个问题),我没有答案。我在https://referencesource.microsoft.com/#mscorlib/system/delegate.cs,2b489eed284b305b处签出了{.1}的.net源,但是我不确定它的工作方式,因为它调用了外部方法CreateDelegate()
和MulticastDelegate InternalAlloc(RuntimeType type)
。我猜想是bool BindToMethodName(Object target, RuntimeType methodType, String method, DelegateBindingFlags flags)
不能完全保留类型信息,还是InternalAlloc
将BindToMethodName
当作Enum
。