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

本文介绍了一种在.NET环境下利用动态代理实现MixIn的方法,通过动态生成类型,使多个类能够混合实现单一接口,同时支持运行时动态替换接口行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

一、应用场景

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

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

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

15            set
16ExpandedSubBlockStart.gifContractedSubBlock.gif            { }
17        }

18    }

19
20      public   class  ClassC
21 ExpandedBlockStart.gifContractedBlock.gif     {
22        public String B(int a, int b)
23ExpandedSubBlockStart.gifContractedSubBlock.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.gifContractedBlock.gif     {
 3        String Heart();
 4        String Lung();
 5        String Name();
 6    }

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

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

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

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

32
33        static void Main(string[] args)
34ExpandedSubBlockStart.gifContractedSubBlock.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 ExpandedBlockStart.gif Code
  1using System;
  2using System.Collections.Generic;
  3using System.Text;
  4using System.Reflection;
  5using System.Reflection.Emit;
  6
  7namespace Orc.Generics
  8ExpandedBlockStart.gifContractedBlock.gif{
  9    public sealed class TypeTemplate
 10ExpandedSubBlockStart.gifContractedSubBlock.gif    {
 11        public class ObjectContainer
 12ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 13            private List<Object> Container = new List<object>();
 14            private List<Type> TypeContainer = new List<Type>();
 15
 16            public ObjectContainer(Object[] objs, Type[] tlist)
 17ExpandedSubBlockStart.gifContractedSubBlock.gif            {
 18                Container.AddRange(objs);
 19                TypeContainer.AddRange(tlist);
 20            }

 21
 22            public Object Get(Int32 index)
 23ExpandedSubBlockStart.gifContractedSubBlock.gif            {
 24                if (index >= 0 && index < Container.Count)
 25                    return Container[index];
 26                else
 27                    return null;
 28            }

 29
 30            public Type GetType(Int32 index)
 31ExpandedSubBlockStart.gifContractedSubBlock.gif            {
 32                if (index >= 0 && index < TypeContainer.Count)
 33                    return TypeContainer[index];
 34                else
 35                    return null;
 36            }

 37
 38            public static MethodInfo GetGetMethodInfo()
 39ExpandedSubBlockStart.gifContractedSubBlock.gif            {
 40                MethodInfo[] mis = typeof(ObjectContainer).GetMethods(BindingFlags.Public | BindingFlags.Instance);
 41                foreach (var mi in mis)
 42ExpandedSubBlockStart.gifContractedSubBlock.gif                {
 43                    if (mi.Name == "Get"return mi;
 44                }

 45                return null;
 46            }

 47        }

 48
 49        private class MethodInfoHolder
 50ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 51ExpandedSubBlockStart.gifContractedSubBlock.gif            public Int32 ObjectIndex getprivate set; }
 52ExpandedSubBlockStart.gifContractedSubBlock.gif            public MethodInfo MethodInfo getprivate set; }
 53ExpandedSubBlockStart.gifContractedSubBlock.gif            public Type ObjectType getprivate set; }
 54            public MethodInfoHolder(MethodInfo pi, Int32 index, Type type)
 55ExpandedSubBlockStart.gifContractedSubBlock.gif            {
 56                MethodInfo = pi;
 57                ObjectIndex = index;
 58                ObjectType = type;
 59            }

 60        }

 61
 62        public delegate void Handler<TImple>(TImple imple) where TImple: class;
 63
 64        public static TInterface Create<TInterface, TImple>(TImple instance) 
 65            where TInterface : class
 66            where TImple : class
 67ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 68ExpandedSubBlockStart.gifContractedSubBlock.gif            Type type = DynamicTypeGen<TInterface>new Object[] { instance }new Type[] { instance.GetType()});
 69ExpandedSubBlockStart.gifContractedSubBlock.gif            return Activator.CreateInstance(type, new ObjectContainer(new Object[] { instance }new Type[] { instance.GetType() })) as TInterface;
 70        }

 71
 72        public static TInterface Create<TInterface>(params Object[] impleInstances)
 73            where TInterface : class
 74ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 75            List<Type> tlist = new List<Type>();
 76            foreach (var item in impleInstances)
 77ExpandedSubBlockStart.gifContractedSubBlock.gif            {
 78                tlist.Add(item.GetType());
 79            }

 80            Type type = DynamicTypeGen<TInterface>(impleInstances, tlist.ToArray());
 81            return Activator.CreateInstance(type, new ObjectContainer( impleInstances, tlist.ToArray())) as TInterface;
 82        }

 83
 84        public static TInterface CreateIntercepted<TInterface, TImple>(TImple instance, Handler<TImple> before, Handler<TImple> after)
 85            where TInterface : class
 86            where TImple : class
 87ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 88            throw new NotImplementedException();
 89        }

 90
 91        public static Type DynamicTypeGen<TInterface>(Object[] instances, Type[] typeList)
 92            where TInterface: class
 93ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 94            Type tInterface = typeof(TInterface);
 95
 96            PropertyInfo[] pisInterface = tInterface.GetProperties(BindingFlags.Public | BindingFlags.Instance);
 97            MethodInfo[] misInterface = tInterface.GetMethods(BindingFlags.Public | BindingFlags.Instance);
 98            List<MethodInfo> misInterfaceList = new List<MethodInfo>();
 99            
100            List<Type> tList = new List<Type>();
101            foreach (var obj in instances)
102ExpandedSubBlockStart.gifContractedSubBlock.gif            {
103                tList.Add(obj.GetType());
104            }

105
106            Type[] tArray = tList.ToArray();
107
108            foreach (var item in misInterface)
109ExpandedSubBlockStart.gifContractedSubBlock.gif            {
110                if (item.IsSpecialName == false) misInterfaceList.Add(item);
111            }

112
113            List<MethodInfoHolder> miHolderList = new List<MethodInfoHolder>();
114            for (int i = 0; i < tArray.Length; i++)
115ExpandedSubBlockStart.gifContractedSubBlock.gif            {
116                MethodInfo[] misImple = tArray[i].GetMethods(BindingFlags.Public | BindingFlags.Instance);
117                foreach (var item in misImple)
118ExpandedSubBlockStart.gifContractedSubBlock.gif                {
119                    MethodInfoHolder h = new MethodInfoHolder(item, i, typeList[i]);
120                    miHolderList.Add(h);
121                }

122            }

123
124            AssemblyName aName = new AssemblyName("Orc.Generics.DynamicTypes");
125            AssemblyBuilder ab =
126                AppDomain.CurrentDomain.DefineDynamicAssembly(
127                    aName,
128                    AssemblyBuilderAccess.RunAndSave);
129            
130            ModuleBuilder mb =
131                ab.DefineDynamicModule(aName.Name, aName.Name + ".dll");
132
133            TypeBuilder tb = mb.DefineType(GetDynamicTypeName<TInterface>(instances),
134ExpandedSubBlockStart.gifContractedSubBlock.gif                TypeAttributes.Public, nullnew Type[] { tInterface });
135            FieldBuilder fbInstances = tb.DefineField(
136                "_container",
137                typeof(TypeTemplate.ObjectContainer),
138                FieldAttributes.Private);
139
140            ConstructorBuilder ctor1 = tb.DefineConstructor(
141                MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.RTSpecialName,
142                CallingConventions.Standard,
143ExpandedSubBlockStart.gifContractedSubBlock.gif                new Type[1typeof(TypeTemplate.ObjectContainer) });
144
145            ILGenerator ctor1IL = ctor1.GetILGenerator();
146            ctor1IL.Emit(OpCodes.Ldarg_0);
147            ctor1IL.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));
148            ctor1IL.Emit(OpCodes.Ldarg_0);
149            ctor1IL.Emit(OpCodes.Ldarg_1);
150            ctor1IL.Emit(OpCodes.Stfld, fbInstances);
151            ctor1IL.Emit(OpCodes.Ret);
152
153            foreach (var item in pisInterface)
154ExpandedSubBlockStart.gifContractedSubBlock.gif            {
155                MethodInfoHolder getMi = FindGetMethodInfo(miHolderList, item);
156                MethodInfoHolder setMi = FindSetMethodInfo(miHolderList, item);
157                CreateProperty(tb, fbInstances, item, getMi, setMi);
158            }

159
160            foreach (var item in misInterfaceList)
161ExpandedSubBlockStart.gifContractedSubBlock.gif            {
162                MethodInfoHolder instanceMi = FindMethodInfo(miHolderList, item);
163                CreateMethod(tb, fbInstances, item, instanceMi);
164            }

165            Type type = tb.CreateType();
166            ab.Save(aName.Name + ".dll");
167            return type;
168        }

169
170        private static MethodInfoHolder FindGetMethodInfo(IEnumerable<MethodInfoHolder> miList, PropertyInfo pi)
171ExpandedSubBlockStart.gifContractedSubBlock.gif        {
172            foreach (var item in miList)
173ExpandedSubBlockStart.gifContractedSubBlock.gif            {
174                if (item.MethodInfo.Name.Equals("get_" + pi.Name) && item.MethodInfo.IsSpecialName) return item;
175            }

176
177            return null;
178        }

179
180        private static MethodInfoHolder FindSetMethodInfo(IEnumerable<MethodInfoHolder> miList, PropertyInfo pi)
181ExpandedSubBlockStart.gifContractedSubBlock.gif        {
182            foreach (var item in miList)
183ExpandedSubBlockStart.gifContractedSubBlock.gif            {
184                if (item.MethodInfo.Name.Equals("set_" + pi.Name) && item.MethodInfo.IsSpecialName) return item;
185            }

186            
187            return null;
188        }

189
190        private static MethodInfoHolder FindMethodInfo(IEnumerable<MethodInfoHolder> miList, MethodInfo mi)
191ExpandedSubBlockStart.gifContractedSubBlock.gif        {
192            foreach (var item in miList)
193ExpandedSubBlockStart.gifContractedSubBlock.gif            {
194                if (MethodInfoEqual(item.MethodInfo,mi)) return item;
195            }

196
197            return null;
198        }

199
200        private static Boolean MethodInfoEqual(MethodInfo mi1, MethodInfo mi2)
201ExpandedSubBlockStart.gifContractedSubBlock.gif        {
202            if (mi1.IsSpecialName == true || mi2.IsSpecialName == truereturn false;
203            if (mi1.Name != mi2.Name) return false;
204            if (mi1.ReturnType != mi2.ReturnType) return false;
205            ParameterInfo[] pis1 = mi1.GetParameters();
206            ParameterInfo[] pis2 = mi2.GetParameters();
207            if (pis1.Length != pis2.Length) return false;
208            for (int i = 0; i < pis1.Length; i++)
209ExpandedSubBlockStart.gifContractedSubBlock.gif            {
210                ParameterInfo pi1 = pis1[i];
211                ParameterInfo pi2 = pis2[i];
212                if (pi1.ParameterType != pi2.ParameterType) return false;
213            }

214            return true;
215        }

216
217        private static void CreateProperty(TypeBuilder tb, FieldBuilder fbInstance, PropertyInfo pi, MethodInfoHolder getMi, MethodInfoHolder setMi)
218ExpandedSubBlockStart.gifContractedSubBlock.gif        {
219            String name = pi.Name;
220            Type type = pi.PropertyType;
221
222            PropertyBuilder pb = tb.DefineProperty(
223                name,
224                PropertyAttributes.HasDefault,
225                type,
226                null);
227
228            MethodAttributes getSetAttr = MethodAttributes.Public |
229                MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final ;
230            MethodBuilder mbGetAccessor = tb.DefineMethod(
231                "get_" + name,
232                getSetAttr,
233                type,
234                Type.EmptyTypes);
235
236            ILGenerator getIL = mbGetAccessor.GetILGenerator();
237            
238            if (getMi == null)
239ExpandedSubBlockStart.gifContractedSubBlock.gif            {
240ExpandedSubBlockStart.gifContractedSubBlock.gif                getIL.Emit(OpCodes.Newobj, typeof(NotImplementedException).GetConstructor(new Type[]{}));
241                getIL.Emit(OpCodes.Throw);
242            }

243            else
244ExpandedSubBlockStart.gifContractedSubBlock.gif            {
245                getIL.Emit(OpCodes.Ldarg_0);
246                getIL.Emit(OpCodes.Ldfld, fbInstance);
247                getIL.Emit(OpCodes.Ldc_I4, getMi.ObjectIndex);
248                getIL.Emit(OpCodes.Callvirt, ObjectContainer.GetGetMethodInfo());
249                getIL.Emit(OpCodes.Isinst, getMi.ObjectType);
250                getIL.Emit(OpCodes.Callvirt, getMi.MethodInfo);
251                getIL.Emit(OpCodes.Ret);
252            }

253
254            MethodBuilder mbSetAccessor = tb.DefineMethod(
255                "set_"+ name,
256                getSetAttr,
257                null,
258ExpandedSubBlockStart.gifContractedSubBlock.gif                new Type[] { type });
259
260            ILGenerator setIL = mbSetAccessor.GetILGenerator();
261            if (setMi == null)
262ExpandedSubBlockStart.gifContractedSubBlock.gif            {
263ExpandedSubBlockStart.gifContractedSubBlock.gif                setIL.Emit(OpCodes.Newobj, typeof(NotImplementedException).GetConstructor(new Type[] { }));
264                setIL.Emit(OpCodes.Throw);
265            }

266            else
267ExpandedSubBlockStart.gifContractedSubBlock.gif            {
268                setIL.Emit(OpCodes.Ldarg_0);
269                setIL.Emit(OpCodes.Ldfld, fbInstance);
270                setIL.Emit(OpCodes.Ldc_I4, setMi.ObjectIndex);
271                setIL.Emit(OpCodes.Callvirt, ObjectContainer.GetGetMethodInfo());
272                setIL.Emit(OpCodes.Isinst, setMi.ObjectType);
273                setIL.Emit(OpCodes.Ldarg_1);
274                setIL.Emit(OpCodes.Callvirt, setMi.MethodInfo);
275                setIL.Emit(OpCodes.Ret);
276            }

277
278            pb.SetGetMethod(mbGetAccessor);
279            pb.SetSetMethod(mbSetAccessor);
280        }

281
282        private static void CreateMethod(TypeBuilder tb, FieldBuilder fbInstance, MethodInfo mi, MethodInfoHolder instanceMi)
283ExpandedSubBlockStart.gifContractedSubBlock.gif        {
284            List<Type> paramTyleList = new List<Type>();
285            foreach(var item in mi.GetParameters())
286                paramTyleList.Add(item.ParameterType);
287
288            MethodBuilder mb = tb.DefineMethod(
289              mi.Name,
290              MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final,
291              mi.ReturnType,
292              paramTyleList.ToArray());
293
294            ILGenerator il = mb.GetILGenerator();
295            if (instanceMi == null)
296ExpandedSubBlockStart.gifContractedSubBlock.gif            {
297ExpandedSubBlockStart.gifContractedSubBlock.gif                il.Emit(OpCodes.Newobj, typeof(NotImplementedException).GetConstructor(new Type[] { }));
298                il.Emit(OpCodes.Throw);
299            }

300            else
301ExpandedSubBlockStart.gifContractedSubBlock.gif            {
302                il.Emit(OpCodes.Ldarg_0);
303                il.Emit(OpCodes.Ldfld, fbInstance);
304                il.Emit(OpCodes.Ldc_I4, instanceMi.ObjectIndex);
305                il.Emit(OpCodes.Callvirt, ObjectContainer.GetGetMethodInfo());
306                il.Emit(OpCodes.Isinst, instanceMi.ObjectType);
307                switch (paramTyleList.Count)
308ExpandedSubBlockStart.gifContractedSubBlock.gif                {
309                    case 0:
310                        break;
311                    case 1:
312                        il.Emit(OpCodes.Ldarg_1);
313                        break;
314                    case 2:
315                        il.Emit(OpCodes.Ldarg_1);
316                        il.Emit(OpCodes.Ldarg_2);
317                        break;
318                    case 3:
319                        il.Emit(OpCodes.Ldarg_1);
320                        il.Emit(OpCodes.Ldarg_2);
321                        il.Emit(OpCodes.Ldarg_3);
322                        break;
323                    default:
324                        il.Emit(OpCodes.Ldarg_1);
325                        il.Emit(OpCodes.Ldarg_2);
326                        il.Emit(OpCodes.Ldarg_3);
327
328                        Int32 sCount = Math.Min(paramTyleList.Count, 127);
329                        for (int i = 4; i <= sCount; i++)
330ExpandedSubBlockStart.gifContractedSubBlock.gif                        {
331                            il.Emit(OpCodes.Ldarg_S, i);
332                        }

333
334                        for (int i = 128; i <= paramTyleList.Count; i++)
335ExpandedSubBlockStart.gifContractedSubBlock.gif                        {
336                            il.Emit(OpCodes.Ldarg, i);
337                        }

338
339                        break;
340                }

341
342                il.Emit(OpCodes.Callvirt, instanceMi.MethodInfo);
343                il.Emit(OpCodes.Ret);
344            }

345        }

346
347        private static String GetDynamicTypeName<TInterface>(params Object[] instances)
348    where TInterface : class
349ExpandedSubBlockStart.gifContractedSubBlock.gif        {
350            StringBuilder sb = new StringBuilder();
351            sb.Append("_DynamicTypes");
352            sb.Append(typeof(TInterface).ToString());
353            foreach (var obj in instances)
354ExpandedSubBlockStart.gifContractedSubBlock.gif            {
355                sb.Append("_");
356                sb.Append(obj.GetType().ToString());
357            }

358            return sb.ToString();
359        }

360    }

361
362    public interface TInterface
363ExpandedSubBlockStart.gifContractedSubBlock.gif    {
364ExpandedSubBlockStart.gifContractedSubBlock.gif        String A get; }
365        String B(int a, int b);
366    }

367
368    public class ClassB
369ExpandedSubBlockStart.gifContractedSubBlock.gif    {
370        public String A
371ExpandedSubBlockStart.gifContractedSubBlock.gif        {
372            get
373ExpandedSubBlockStart.gifContractedSubBlock.gif            {
374                return String.Empty;
375            }

376            set
377ExpandedSubBlockStart.gifContractedSubBlock.gif            { }
378        }

379    }

380
381    public class ClassC
382ExpandedSubBlockStart.gifContractedSubBlock.gif    {
383        public String B(int a, int b)
384ExpandedSubBlockStart.gifContractedSubBlock.gif        {
385            return (a + b).ToString();
386        }

387    }

388
389    public class ClassA
390ExpandedSubBlockStart.gifContractedSubBlock.gif    {
391        public String A 
392ExpandedSubBlockStart.gifContractedSubBlock.gif        {
393            get
394ExpandedSubBlockStart.gifContractedSubBlock.gif            {
395                return String.Empty;
396            }

397            set
398ExpandedSubBlockStart.gifContractedSubBlock.gif            { }
399        }

400
401        public String B(int a, int b)
402ExpandedSubBlockStart.gifContractedSubBlock.gif        {
403            return (a+b).ToString();
404        }

405    }

406
407    public class InterfaceImple_ClassA : TInterface
408ExpandedSubBlockStart.gifContractedSubBlock.gif    {
409        private TypeTemplate.ObjectContainer __container;
410
411        public InterfaceImple_ClassA(TypeTemplate.ObjectContainer container)
412ExpandedSubBlockStart.gifContractedSubBlock.gif        {
413            __container = container;
414        }

415
416        public String A
417ExpandedSubBlockStart.gifContractedSubBlock.gif        {
418ExpandedSubBlockStart.gifContractedSubBlock.gif            get return (__container.Get(1as ClassA).A; }
419ExpandedSubBlockStart.gifContractedSubBlock.gif            set { (__container.Get(1as ClassA).A = value; }
420        }

421
422        public String B(int a, int b)
423ExpandedSubBlockStart.gifContractedSubBlock.gif        {
424            return (__container.Get(1as ClassA).B(a, b);
425        }

426    }

427
428    public class InterfaceImple_ClassA_Factory
429ExpandedSubBlockStart.gifContractedSubBlock.gif    {
430        public readonly String Name = "InterfaceImple_ClassA_Factory";
431        public InterfaceImple_ClassA Create(ClassA a)
432ExpandedSubBlockStart.gifContractedSubBlock.gif        {
433            return null;
434            // return new InterfaceImple_ClassA(new Object[] {a});
435        }

436    }

437}

438

 

测试代码:

 1         [TestMethod]
 2          public   void  TestCreate()
 3 ExpandedBlockStart.gifContractedBlock.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也根据被代理的对象的行为动态生成,那就很爽了。怎么实现,是一个问题。

转载于:https://www.cnblogs.com/xiaotie/archive/2009/02/01/1381973.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值