c# - 当多个方法仅在 1 个枚举参数中不同时,Delegate.CreateDelegate() 创建错误的委托
问题描述
我在为我的类的某些方法创建正确的委托时遇到了一些问题。有一个基类和一个派生类,都有一个方法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)
创建一个错误函数的委托?给定的类型是否不足以确定正确的类型?
解决方案
显然,委托的构造函数比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 的 .net 源代码CreateDelegate()
,但我不太确定它是如何工作的,因为它调用外部方法MulticastDelegate InternalAlloc(RuntimeType type)
和bool BindToMethodName(Object target, RuntimeType methodType, String method, DelegateBindingFlags flags)
. 我猜想要么类型信息没有被 完全保留,InternalAlloc
要么BindToMethodName
将.Enum
int
推荐阅读
- python - 如何创建以列为数组的熊猫数据框
- ruby-on-rails - 在 activeadmin 表单中的复选框标签旁边添加图像
- typescript - Typescript 获取“import * as whatIsMyType from './foo';”的类型
- azure - GET 请求有效,POST 请求无效(Microsoft Azure South Central US)
- java - 如何在 Lucene 7.4 中索引短字段
- selenium-webdriver - 在自动化测试中打开浏览器的页面对象模型中的标准做法是什么?
- javascript - 带有异步调用的 ES6 循环
- javascript - Sequelizejs 通过两个字段“包含”
- excel - PowerQuery 合并表的结果不是默认顺序
- c# - 对二维数组列表进行排序