当多个方法仅在1个enum参数中不同时,Delegate.CreateDelegate()会创建错误的委托

问题描述 投票:1回答:1

我有一些问题为我的类的某些方法创建正确的委托。有一个基类和一个派生类,都有一个方法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)创建了错误函数的委托?给定的类型不足以确定正确的类型吗?

c# delegates
1个回答
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的正确过载。

至于为什么这是必要的(这是我的第二个问题),我没有答案。我在CreateDelegate()检查了https://referencesource.microsoft.com/#mscorlib/system/delegate.cs,2b489eed284b305b的.net源代码,但我不太清楚它是如何工作的,因为它调用了外部方法MulticastDelegate InternalAlloc(RuntimeType type)bool BindToMethodName(Object target, RuntimeType methodType, String method, DelegateBindingFlags flags)。我想InternalAlloc没有完全保留类型信息,或者BindToMethodNameEnum作为int

© www.soinside.com 2019 - 2024. All rights reserved.