实现.net下的动态代理(续)-多对象Mixin

简介:

实现.net下的动态代理 一文使用动态代理实现了 Ducking Typing,解决了文中的第一个问题,下面,向第二个问题进军——mixin。

一、应用场景

(1) 假定有一个接口TInterface,一个类B,类C。类B与类C分别实现了部分TInterface:

复制代码
 1      public   interface  TInterface
 2 ExpandedBlockStart.gif     {
 3ExpandedSubBlockStart.gif        String A get; }
 4        String B(int a, int b);
 5    }

 6
 7      public   class  ClassB
 8 ExpandedBlockStart.gif     {
 9        public String A
10ExpandedSubBlockStart.gif        {
11            get
12ExpandedSubBlockStart.gif            {
13                return String.Empty;
14            }

15            set
16ExpandedSubBlockStart.gif            { }
17        }

18    }

19
20      public   class  ClassC
21 ExpandedBlockStart.gif     {
22        public String B(int a, int b)
23ExpandedSubBlockStart.gif        {
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) 通过Mixin,我们还可以在运行时动态替换接口的指定方法或属性:

复制代码
 1      public   interface  Human
 2 ExpandedBlockStart.gif     {
 3        String Heart();
 4        String Lung();
 5        String Name();
 6    }

 7
 8      public   class  ZhouBapi : Human
 9 ExpandedBlockStart.gif     {
10ExpandedSubBlockStart.gif        public String Heart() return "好心"; }
11ExpandedSubBlockStart.gif        public String Lung() return "好肺"; }
12ExpandedSubBlockStart.gif        public String Name() return "周扒皮"; }
13    }

14
15      public   class  Huaidan
16 ExpandedBlockStart.gif     {
17ExpandedSubBlockStart.gif        public String Heart() return "狼心"; }
18ExpandedSubBlockStart.gif        public String Lung() return "狗肺"; }
19    }

20
21      class  Program
22 ExpandedBlockStart.gif     {
23        static void Show(Human body)
24ExpandedSubBlockStart.gif        {
25            Console.WriteLine(String.Format("我叫{0},我是{1}{2}", body.Name(), body.Heart(), body.Lung()));
26        }

27
28        static void ShowHuaidan(Human body)
29ExpandedSubBlockStart.gif        {
30            Console.WriteLine(String.Format("{0},我看你是{1}{2}", body.Name(), body.Heart(), body.Lung()));
31        }

32
33        static void Main(string[] args)
34ExpandedSubBlockStart.gif        {
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    }
复制代码

 

输出为:

周扒皮: 我叫周扒皮,我是好心好肺
人民群众:周扒皮,我看你是狼心狗肺

 

二、实现

以下是详细实现代码:

 

ContractedBlock.gif Code

 

测试代码:

复制代码
 1         [TestMethod]
 2          public   void  TestCreate()
 3 ExpandedBlockStart.gif         {
 4            ClassA a = new ClassA();
 5            TInterface i1 = TypeTemplate.Create<TInterface, ClassA>(a);
 6            Assert.AreNotEqual(null, i1);
 7            Assert.AreEqual("3", i1.B(12));
 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(12));
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)

相关文章
|
8月前
|
容器
.NET Core-作用域与对象释放行为详解
.NET Core-作用域与对象释放行为详解
|
8天前
|
C#
.NET开发中合理使用对象映射库,简化和提高工作效率
.NET开发中合理使用对象映射库,简化和提高工作效率
106 0
|
8月前
|
JSON 数据格式
.NET Core - 配置绑定:使用强类型对象承载配置数据
.NET Core - 配置绑定:使用强类型对象承载配置数据
|
8月前
|
容器
.NET Core作用域与对象释放行为详解
上节,我们提到,容器中有3种不同生命周期,分别是Singleton、Scoped和Transient。那么,你知道这3种类型的对象的释放时机和坑吗?
|
10月前
|
SQL 存储 缓存
SQl Server——ADO.NET五大对象
在某些编程中总是会需要用到数据库,那如何让应用程序和数据库之间建立联系呢?ADO.NET就提供了应用程序连接数据库的桥梁
|
机器学习/深度学习 人工智能 计算机视觉
YOLOv7 在 ML.NET 中使用 ONNX 检测对象
本文介绍如何在 ML.NET 中使用 YOLOv7 的 ONNX 模型来检测图像中的对象。
296 0
YOLOv7 在 ML.NET 中使用 ONNX 检测对象
|
开发框架 移动开发 前端开发
ASP.NET MVC中使用jQuery Ajax通过FormData对象异步提交图片文件到服务端保存并返回保存的图片路径
ASP.NET MVC中使用jQuery Ajax通过FormData对象异步提交图片文件到服务端保存并返回保存的图片路径
254 0
C#编程-64:ADO.NET对象模型复习笔记
C#编程-64:ADO.NET对象模型复习笔记
C#编程-64:ADO.NET对象模型复习笔记
|
存储 C#
【.Net底层剖析】2.stfld指令-给对象的字段赋值
【.Net底层剖析】2.stfld指令-给对象的字段赋值
130 0
【.Net底层剖析】2.stfld指令-给对象的字段赋值