.Net学习难点讨论系列7 - .NET委托补充
近日开始读园子炒得比较热的王翔老师的新作,初看第一章内容比较对我口味,委托中还有很多不懂的,顺手记了下来。
预备知识
Delegate中的静态方法
Delegate.CreateDelegate()方法
在一般情况下,我们直接调用委托的构造函数来生成一个委托对象,但有些情况下我们需要使用CreateDelegate()静态方法来创建一个指定类型的委托实例。此方法有多种重载,见下表(摘自MSDN):
名称 |
说明 |
Delegate.CreateDelegate (Type, MethodInfo) |
创建指定类型的委托以表示指定的静态方法。 |
Delegate.CreateDelegate (Type, MethodInfo, Boolean) |
使用针对绑定失败的指定行为,创建用于表示指定静态方法的指定类型的委托。 |
Delegate.CreateDelegate (Type, Object, MethodInfo) |
使用指定的第一个参数创建指定类型的委托,该委托表示指定的静态方法或实例方法。 |
Delegate.CreateDelegate (Type, Object, String) |
创建指定类型的委托,该委托表示要对指定的类实例调用的指定实例方法。 |
Delegate.CreateDelegate (Type, Type, String) |
创建指定类型的委托,该委托表示指定类的指定静态方法。 |
Delegate.CreateDelegate (Type, Object, MethodInfo, Boolean) |
使用指定的第一个参数和针对绑定失败的指定行为,创建表示指定的静态方法或实例方法的指定类型的委托。 |
Delegate.CreateDelegate (Type, Object, String, Boolean) |
创建指定类型的委托,该委托表示要按指定的大小写敏感度对指定类实例调用的指定实例方法。 |
Delegate.CreateDelegate (Type, Type, String, Boolean) |
使用用于指定是否区分大小写的值创建指定类型的委托,该委托表示指定类的指定静态方法。 |
Delegate.CreateDelegate (Type, Object, String, Boolean, Boolean) |
使用用于指定是否区分大小写的值和针对绑定失败的指定行为,创建指定类型的委托,该委托表示要对指定类实例调用的指定实例方法。 |
Delegate.CreateDelegate (Type, Type, String, Boolean, Boolean) |
使用用于指定是否区分大小写的值和针对绑定失败的指定行为,创建指定类型的委托,该委托表示指定类的指定静态方法。 |
重点介绍一个下文将要用到的重载:
1 public static Delegate CreateDelegate ( 2 Type type, 3 Object target, 4 string method 5 )
参数
- type: 要创建的委托的 Type。
- target: 类实例,对其调用method。
- method: 委托要表示的实例方法的名称。
返回值
指定的类型的委托,表示要对指定的类实例调用的指定的实例方法。
Delegate.Combine()方法
该方法用于将指定的多路广播(可组合)委托的调用列表连接起来。在内部Combine()方法是重载的+=运算符的内部实现。用+=进行的委托多路调用都将被编译为对Combine方法的调用。
Combine()方法的两个重载:
名称 |
说明 |
Delegate.Combine (Delegate[]) |
将委托数组的调用列表连接在一起。 |
Delegate.Combine (Delegate, Delegate) |
将两个委托的调用列表连接在一起。 |
下面是来自书中的一个示例,使用了上述静态方法。
示例的场景是委托需要调用的方法有新的重载,作者在书中给出了下面这个近乎最佳的实现方式:
声明委托及调用重载方法的代码:
1 using System; 2 using System.Collections.Generic; 3 namespace MarvellousWorks.PracticalPattern.Concept.Delegating 4 { 5 public delegate void MemoHandler(int x, int y, IDictionary<string, int> data); 6 7 // 对具有重载的多个目标方法Delegate 8 public class OverloadableDelegateInvoker 9 { 10 private MemoHandler handler; 11 12 public OverloadableDelegateInvoker() 13 { 14 Type type = typeof(MemoHandler); 15 Delegate d = Delegate.CreateDelegate(type, new C1(), "A"); 16 d = Delegate.Combine(d, Delegate.CreateDelegate(type, new C2(), "S")); 17 d = Delegate.Combine(d, Delegate.CreateDelegate(type, new C3(), "M")); 18 handler = (MemoHandler)d; 19 } 20 21 public void Memo(int x, int y, IDictionary<string, int> data) 22 { 23 handler(x, y, data); 24 } 25 } 26 }
其中用到的重载的几个函数所在的类:
1 // 重载+ 2 public sealed class C1 3 { 4 void A(int x, IDictionary<string, int> data) { data["A"] = x; } 5 void A(int x, int y, IDictionary<string, int> data) { data["A"] = x + y; } 6 } 7 8 // 重载- 9 public sealed class C2 10 { 11 void S(int x, IDictionary<string, int> data) { data["S"] = x; } 12 void S(int x, int y, IDictionary<string, int> data) { data["S"] = x - y; } 13 } 14 15 // 重载* 16 public sealed class C3 17 { 18 void M(int x, int y, IDictionary<string, int> data) { data["M"] = x * y; } 19 }
测试上述委托代码的类(使用VS2005):
1 using System.Collections.Generic; 2 using Microsoft.VisualStudio.TestTools.UnitTesting; 3 using MarvellousWorks.PracticalPattern.Concept.Delegating; 4 namespace MarvellousWorks.PracticalPattern.Concept.Test 5 { 6 [TestClass()] 7 public class OverloadMulticastDelegateInvokerTest 8 { 9 [TestMethod] 10 public void Test() 11 { 12 int result = 10; 13 int expected = result; 14 OverloadableDelegateInvoker invoker = new OverloadableDelegateInvoker(); 15 IDictionary<string, int> data = new Dictionary<string, int>(); 16 invoker.Memo(1, 2, data); 17 Assert.AreEqual<int>(1 + 2, data["A"]); 18 Assert.AreEqual<int>(1 - 2, data["S"]); 19 Assert.AreEqual<int>(1 * 2, data["M"]); 20 } 21 } 22 }