如何通过反射向已有委托添加另一个委托实例?
问题描述
我不清楚如何转换变量d以使用+=运算符向其添加新方法。是否存在最简解决方案?如前文所述,初始委托存在于类外部,必须通过反射修改(不得使用表达式、表达式树、Emit等方式)。
当前代码在不使用+=时可正常运行,输出内容为:
b.fn() a.fn()
相关代码如下:
using System; using System.Reflection; public class A { public void fn() { Console.WriteLine ("a.fn() \n"); } public void fn1() { Console.WriteLine ("a.fn1()"); } void start() { var cb = new B(); FieldInfo fi = cb.GetType().GetField("mD"); MethodInfo mfn = this.GetType().GetMethod("fn"); object d = System.Delegate.CreateDelegate( fi.FieldType, this, mfn); // d += System.Delegate.CreateDelegate( fi.FieldType, this, mfn1); // Line above give me an error CS0019: Operator '+=' cannot be applied to operands of type 'object' and 'Delegate' // I think it due d is object not MD() fi.SetValue(cb, d); cb.tst(); } public static void Main(string[] args) { var ca = new A(); ca.start(); } } public class B { public delegate void MD(); public MD mD ; public B() { mD = fn; tst(); } public void tst() { mD(); } void fn() { Console.WriteLine ("b.fn() \n"); } }
解决方案
因为变量d被声明为object类型,无法直接使用+=运算符(该运算符仅对具体委托类型或Delegate基类有效),最简方案是使用Delegate.Combine方法来合并委托——它是+=运算符的底层实现,能自动处理委托链拼接,具体修改如下:
将注释掉的报错行替换为:
// 先将d强制转为Delegate类型,再与新创建的委托合并 d = Delegate.Combine((Delegate)d, Delegate.CreateDelegate(fi.FieldType, this, GetType().GetMethod("fn1")));
完整修改后的start方法代码:
void start() { var cb = new B(); FieldInfo fi = cb.GetType().GetField("mD"); MethodInfo mfn = this.GetType().GetMethod("fn"); object d = System.Delegate.CreateDelegate(fi.FieldType, this, mfn); // 合并委托 d = Delegate.Combine((Delegate)d, Delegate.CreateDelegate(fi.FieldType, this, GetType().GetMethod("fn1"))); fi.SetValue(cb, d); cb.tst(); }
说明
Delegate.Combine是.NET官方提供的委托合并方法,+=运算符本质就是该方法的语法糖。- 由于
d是object类型,必须先强制转换为Delegate基类才能传入Combine方法。 - 合并后的委托仍保持原委托类型(此处为
B.MD),可直接通过SetValue赋值给目标字段。
修改后运行代码,输出结果为:
b.fn() a.fn() a.fn1()
内容的提问来源于stack exchange,提问作者SimpleCoder
相关产品推荐
相关产品推荐

