实现.net下的动态代理 一文使用动态代理实现了 Ducking Typing,解决了文中的第一个问题,下面,向第二个问题进军——mixin。
一、应用场景
(1) 假定有一个接口TInterface,一个类B,类C。类B与类C分别实现了部分TInterface:
1
public
interface
TInterface
2 {
3 String A { get; }
4 String B(int a, int b);
5 }
6
7 public class ClassB
8 {
9 public String A
10 {
11 get
12 {
13 return String.Empty;
14 }
15 set
16 { }
17 }
18 }
19
20 public class ClassC
21 {
22 public String B(int a, int b)
23 {
24 return (a + b).ToString();
25 }
26 }
2 {
3 String A { get; }
4 String B(int a, int b);
5 }
6
7 public class ClassB
8 {
9 public String A
10 {
11 get
12 {
13 return String.Empty;
14 }
15 set
16 { }
17 }
18 }
19
20 public class ClassC
21 {
22 public String B(int a, int b)
23 {
24 return (a + b).ToString();
25 }
26 }
假设b和c分别是B和C的一个实例,通过 TypeTemplate.Create<TInterface>(b,c) 方法将b和c包装一下,即可生成一个TInterface实例:
1
ClassB b
=
new
ClassB();
2 ClassC c = new ClassC();
3 TInterface i2 = TypeTemplate.Create < TInterface > (b, c);
4
2 ClassC c = new ClassC();
3 TInterface i2 = TypeTemplate.Create < TInterface > (b, c);
4
(2) 通过Mixin,我们还可以在运行时动态替换接口的指定方法或属性:
1
public
interface
Human
2 {
3 String Heart();
4 String Lung();
5 String Name();
6 }
7
8 public class ZhouBapi : Human
9 {
10 public String Heart() { return "好心"; }
11 public String Lung() { return "好肺"; }
12 public String Name() { return "周扒皮"; }
13 }
14
15 public class Huaidan
16 {
17 public String Heart() { return "狼心"; }
18 public String Lung() { return "狗肺"; }
19 }
20
21 class Program
22 {
23 static void Show(Human body)
24 {
25 Console.WriteLine(String.Format("我叫{0},我是{1}{2}", body.Name(), body.Heart(), body.Lung()));
26 }
27
28 static void ShowHuaidan(Human body)
29 {
30 Console.WriteLine(String.Format("{0},我看你是{1}{2}", body.Name(), body.Heart(), body.Lung()));
31 }
32
33 static void Main(string[] args)
34 {
35 Human zhou = new ZhouBapi();
36 Console.Write("周扒皮: ");
37 Show(zhou);
38 zhou = TypeTemplate.Create<Human>(new Huaidan(), zhou);
39 Console.Write("人民群众:");
40 ShowHuaidan(zhou);
41 Console.Read();
42 }
43 }
2 {
3 String Heart();
4 String Lung();
5 String Name();
6 }
7
8 public class ZhouBapi : Human
9 {
10 public String Heart() { return "好心"; }
11 public String Lung() { return "好肺"; }
12 public String Name() { return "周扒皮"; }
13 }
14
15 public class Huaidan
16 {
17 public String Heart() { return "狼心"; }
18 public String Lung() { return "狗肺"; }
19 }
20
21 class Program
22 {
23 static void Show(Human body)
24 {
25 Console.WriteLine(String.Format("我叫{0},我是{1}{2}", body.Name(), body.Heart(), body.Lung()));
26 }
27
28 static void ShowHuaidan(Human body)
29 {
30 Console.WriteLine(String.Format("{0},我看你是{1}{2}", body.Name(), body.Heart(), body.Lung()));
31 }
32
33 static void Main(string[] args)
34 {
35 Human zhou = new ZhouBapi();
36 Console.Write("周扒皮: ");
37 Show(zhou);
38 zhou = TypeTemplate.Create<Human>(new Huaidan(), zhou);
39 Console.Write("人民群众:");
40 ShowHuaidan(zhou);
41 Console.Read();
42 }
43 }
输出为:
周扒皮: 我叫周扒皮,我是好心好肺
人民群众:周扒皮,我看你是狼心狗肺
人民群众:周扒皮,我看你是狼心狗肺
二、实现
以下是详细实现代码:
Code
测试代码:
1
[TestMethod]
2 public void TestCreate()
3 {
4 ClassA a = new ClassA();
5 TInterface i1 = TypeTemplate.Create<TInterface, ClassA>(a);
6 Assert.AreNotEqual(null, i1);
7 Assert.AreEqual("3", i1.B(1, 2));
8 Assert.AreEqual(String.Empty, i1.A);
9
10 ClassB b = new ClassB();
11 ClassC c = new ClassC();
12 TInterface i2 = TypeTemplate.Create<TInterface>(b, c);
13 Assert.AreNotEqual(null, i2);
14 Assert.AreEqual("3", i2.B(1, 2));
15 Assert.AreEqual(String.Empty, i2.A);
16 }
17
2 public void TestCreate()
3 {
4 ClassA a = new ClassA();
5 TInterface i1 = TypeTemplate.Create<TInterface, ClassA>(a);
6 Assert.AreNotEqual(null, i1);
7 Assert.AreEqual("3", i1.B(1, 2));
8 Assert.AreEqual(String.Empty, i1.A);
9
10 ClassB b = new ClassB();
11 ClassC c = new ClassC();
12 TInterface i2 = TypeTemplate.Create<TInterface>(b, c);
13 Assert.AreNotEqual(null, i2);
14 Assert.AreEqual("3", i2.B(1, 2));
15 Assert.AreEqual(String.Empty, i2.A);
16 }
17
三、说明:
(1)通过上述方法可以很方便的创建对现有实例的Wrapper,使其适应一个新的接口;
(2)TypeTemplate.Create<TInterface>(params Object[] impleInstances) 排位在前的 impleInstance 的接口方法/属性将掩盖它后面的 impleInstance 的接口方法/属性,这样可以在运行时动态改变接口的行为。
(3)这种MixIn方案比不上动态语言的MixIn,主要是必须要有一个interface,才能MixIn。如果能将interface也根据被代理的对象的行为动态生成,那就很爽了。怎么实现,是一个问题。
本文xiaotie博客园博客,原文链接http://www.cnblogs.com/xiaotie/archive/2009/02/01/1381973.html如需转载请自行联系原作者
xiaotie 集异璧实验室(GEBLAB)