实现.net下的动态代理
2009-02-07 09:58 宝宝合凤凰 阅读(452) 评论(1) 收藏 举报
一、动态代理可以解决哪些问题
本文描述的动态代理可以解决以下问题:
问题1:接口约束问题
场景A:ComboBox类与ToolStripComboBox类的行为大部分相似,它们却不共享某个粒度较大的接口,以至于对这两个类的操作代码难以公用。
场景B:在泛型程序中,我们必需为泛型类型声明一个接口约束,才能使用该类型所对应接口约束的方法与属性。这样以来有一个问题:存在接口A,类型B,A中的所有属性和方法签名B都有,但B不是A的实现,不能由B转换为A。而由于某些原因,我们无法获得B的代码或者虽然能够获得B的代码,却由于种种考虑不能更改B的代码;
大多数情况下,可以新写一个类C,使类C继承自B,再让C实现接口A。然而,其一,代码量较大;其二,当B为Sealed时不能继承;其三:不方便使用继承(如:继承后,IDE中的设计器无法给新类提供支持)。
此时,我们希望动态代理能解决这个问题:
假定我们有一个接口:
 public interface TInterface
    public interface TInterface2
 {
    {3
 String A { get; }
        String A { get; }4
 String B(Object a, Object b, Object c, Object d, Object e);
        String B(Object a, Object b, Object c, Object d, Object e);5
 }
    }6

有一个类:
 public class ClassA
    public class ClassA2
 {
    {3
 public String A
        public String A 4
 {
        {5
 get
            get6
 {
            {7
 return String.Empty;
                return String.Empty;8
 }
            }9
 }
        }10

11
 public String B(Object a, Object b, Object c, Object d, Object e)
        public String B(Object a, Object b, Object c, Object d, Object e)12
 {
        {13
 return String.Empty;
            return String.Empty;14
 }
        }15
 }
    }16

17

我们需要这个动态代理类(假定为 TypeTemplate)提供一个方法,能够方便的生成一个代理类实例,将ClassA的实例包装一下,转变为 TInterface 的实例:
 public static TInterface Create<TInterface, TImple>(TImple instance)
        public static TInterface Create<TInterface, TImple>(TImple instance) 2
 where TInterface : class
            where TInterface : class3
 where TImple : class
            where TImple : class4
 {
        {5
 ……
            ……6
 }
        }7

该方法生成一个实现TInterface的动态类的实例。对于TInterface中的每一个属性或方法,该实例直接调用instance实例中具有同样签名的属性或方法,如果没有匹配的属性或方法,则抛出NotImplementedException异常。
问题2:快速生成现有实例类的Wrapper
场景C:假定接口TInterface有10个方法,类TImple中有9个方法与TInterface对应,为了实现TInterface,需要新写一个Wrapper类。最方便的写法是令Wrapper继承自TImple且实现接口TInterface,Wrapper只需新添实现那个未实现的方法即可。然而,如前面所述,很多情况下使用继承不是最佳选择。不用继承的话,则需要Wrapper类实现TInterface的全部10个方法,枯燥又乏味。
此时,我们期待存在这样一种动态代理:它能够将几个实例B,C,D一起打包,使它适合接口A。这样一来,针对场景C,我们只需要写一个简单的Wrapper类,实现那个未实现的方法,然后与TImple实例一起由动态代理工厂打包生成一个新的代理类实例即可。
即:我们需要动态代理工厂TypeTemplate能够提供以下方法:
 public static TInterface Create<TInterface>(TInterface instance, params Object[] impleInstances)
        public static TInterface Create<TInterface>(TInterface instance, params Object[] impleInstances)2
 where TInterface : class
            where TInterface : class3
 {
        {4
 …
            …5
 }
        }6

该方法生成一个实现TInterface的类实例。对于TInterface中的每一个属性或方法,该实例依次从impleInstances中寻找具有同样签名的属性或方法,如果没有匹配的属性或方法,则抛出NotImplementedException异常。
问题3:AOP应用
场景D:当需要对方法进行拦截时我们需要动态代理。
AOP是动态代理最经典的应用,无需赘述。
这种情况下,我们需要 TypeTemplate 类提供以下的方法向代理类中加入钩子:
 public delegate void Handler<TImple>(TImple imple) where TImple: class;
        public delegate void Handler<TImple>(TImple imple) where TImple: class;2

3
 public static TInterface CreateIntercepted<TInterface, TImple>(TImple instance, Handler<TImple> before, Handler<TImple> after)
        public static TInterface CreateIntercepted<TInterface, TImple>(TImple instance, Handler<TImple> before, Handler<TImple> after)4
 where TInterface : class
            where TInterface : class5
 where TImple : class
            where TImple : class6
 {
        {7
 …
            …8
 }
        }9

二、实现
下面来实现动态代理类工厂TypeTemplate。由于时间有限,只实现 static TInterface Create<TInterface, TImple>(TImple instance) 方法原型。其它几个静态方法可以用类似的方式实现。
实现思路:
对于问题1中的接口TInterface和类ClassA,通过Emit生成如下类型InterfaceImple_ClassA的IL代码。
 public class InterfaceImple_ClassA : TInterface
    public class InterfaceImple_ClassA : TInterface2
 {
    {3
 private ClassA __wrappedInstance;
        private ClassA __wrappedInstance;4

5
 public InterfaceImple_ClassA(ClassA instance)
        public InterfaceImple_ClassA(ClassA instance)6
 {
        {7
 __wrappedInstance = instance;
            __wrappedInstance = instance;8
 }
        }9

10
 public String A
        public String A11
 {
        {12
 get { return __wrappedInstance.A; }
            get { return __wrappedInstance.A; }13
 set { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }14
 }
        }15

16
 public String B(Object a, Object b, Object c, Object d, Object e)
        public String B(Object a, Object b, Object c, Object d, Object e)17
 {
        {18
 return __wrappedInstance.B(a,b,c,d,e);
            return __wrappedInstance.B(a,b,c,d,e);19
 }
        }20
 }
    }21

22

假定生成上面这个类型的方法为:
 public static Type DynamicTypeGen<TInterface, TImple>()
        public static Type DynamicTypeGen<TInterface, TImple>()2
 where TInterface: class where TImple : class
            where TInterface: class where TImple : class3

4

则可用Activator轻松生成动态代理类实例:
 public static TInterface Create<TInterface, TImple>(TImple instance)
        public static TInterface Create<TInterface, TImple>(TImple instance) 2
 where TInterface : class
            where TInterface : class3
 where TImple : class
            where TImple : class4
 {
        {5
 Type type = DynamicTypeGen<TInterface, TImple>();
            Type type = DynamicTypeGen<TInterface, TImple>();6
 return Activator.CreateInstance(type, instance) as TInterface;
            return Activator.CreateInstance(type, instance) as TInterface;7
 }
        }8

下面是具体代码:

1
 using System;
using System;2
 using System.Collections.Generic;
using System.Collections.Generic;3
 using System.Text;
using System.Text;4
 using System.Reflection;
using System.Reflection;5
 using System.Reflection.Emit;
using System.Reflection.Emit;6

7
 namespace Orc.Generics
namespace Orc.Generics8
 {
{9
 public sealed class TypeTemplate
    public sealed class TypeTemplate10
 {
    {11
 public delegate void Handler<TImple>(TImple imple) where TImple: class;
        public delegate void Handler<TImple>(TImple imple) where TImple: class;12

13
 public static TInterface Create<TInterface, TImple>(TImple instance)
        public static TInterface Create<TInterface, TImple>(TImple instance) 14
 where TInterface : class
            where TInterface : class15
 where TImple : class
            where TImple : class16
 {
        {17
 Type type = DynamicTypeGen<TInterface, TImple>();
            Type type = DynamicTypeGen<TInterface, TImple>();18
 return Activator.CreateInstance(type, instance) as TInterface;
            return Activator.CreateInstance(type, instance) as TInterface;19
 }
        }20

21
 public static TInterface Create<TInterface>(TInterface instance, params Object[] impleInstances)
        public static TInterface Create<TInterface>(TInterface instance, params Object[] impleInstances)22
 where TInterface : class
            where TInterface : class23
 {
        {24
 throw new NotImplementedException();
            throw new NotImplementedException();25
 }
        }26

27
 public static TInterface CreateIntercepted<TInterface, TImple>(TImple instance, Handler<TImple> before, Handler<TImple> after)
        public static TInterface CreateIntercepted<TInterface, TImple>(TImple instance, Handler<TImple> before, Handler<TImple> after)28
 where TInterface : class
            where TInterface : class29
 where TImple : class
            where TImple : class30
 {
        {31
 throw new NotImplementedException();
            throw new NotImplementedException();32
 }
        }33

34
 public static Type DynamicTypeGen<TInterface, TImple>()
        public static Type DynamicTypeGen<TInterface, TImple>()35
 where TInterface: class where TImple : class
            where TInterface: class where TImple : class36
 {
        {37
 Type tInterface = typeof(TInterface);
            Type tInterface = typeof(TInterface);38
 Type tImple = typeof(TImple);
            Type tImple = typeof(TImple);39

40
 PropertyInfo[] pisInterface = tInterface.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            PropertyInfo[] pisInterface = tInterface.GetProperties(BindingFlags.Public | BindingFlags.Instance);41
 MethodInfo[] misInterface = tInterface.GetMethods(BindingFlags.Public | BindingFlags.Instance);
            MethodInfo[] misInterface = tInterface.GetMethods(BindingFlags.Public | BindingFlags.Instance);42
 List<MethodInfo> misInterfaceList = new List<MethodInfo>();
            List<MethodInfo> misInterfaceList = new List<MethodInfo>();43
 foreach (var item in misInterface)
            foreach (var item in misInterface)44
 {
            {45
 if (item.IsSpecialName == false) misInterfaceList.Add(item);
                if (item.IsSpecialName == false) misInterfaceList.Add(item);46
 }
            }47

48
 MethodInfo[] misImple = tImple.GetMethods(BindingFlags.Public | BindingFlags.Instance);
            MethodInfo[] misImple = tImple.GetMethods(BindingFlags.Public | BindingFlags.Instance);49
 AssemblyName aName = new AssemblyName("Orc.Generics.DynamicTypes");
            AssemblyName aName = new AssemblyName("Orc.Generics.DynamicTypes");50
 AssemblyBuilder ab =
            AssemblyBuilder ab =51
 AppDomain.CurrentDomain.DefineDynamicAssembly(
                AppDomain.CurrentDomain.DefineDynamicAssembly(52
 aName,
                    aName,53
 AssemblyBuilderAccess.RunAndSave);
                    AssemblyBuilderAccess.RunAndSave);54
 ModuleBuilder mb =
            ModuleBuilder mb =55
 ab.DefineDynamicModule(aName.Name, aName.Name + ".dll");
                ab.DefineDynamicModule(aName.Name, aName.Name + ".dll");56
 TypeBuilder tb = mb.DefineType(GetDynamicTypeName<TInterface, TImple>(),
            TypeBuilder tb = mb.DefineType(GetDynamicTypeName<TInterface, TImple>(),57
 TypeAttributes.Public, null, new Type[] { tInterface });
                TypeAttributes.Public, null, new Type[] { tInterface });58
 FieldBuilder fbInstance = tb.DefineField(
            FieldBuilder fbInstance = tb.DefineField(59
 "__wrappedInstance",
                "__wrappedInstance",60
 tImple,
                tImple,61
 FieldAttributes.Private);
                FieldAttributes.Private);62

63
 ConstructorBuilder ctor1 = tb.DefineConstructor(
            ConstructorBuilder ctor1 = tb.DefineConstructor(64
 MethodAttributes.Public,
                MethodAttributes.Public,65
 CallingConventions.Standard,
                CallingConventions.Standard,66
 new Type[] {tImple});
                new Type[] {tImple});67

68
 ILGenerator ctor1IL = ctor1.GetILGenerator();
            ILGenerator ctor1IL = ctor1.GetILGenerator();69
 ctor1IL.Emit(OpCodes.Ldarg_0);
            ctor1IL.Emit(OpCodes.Ldarg_0);70
 ctor1IL.Emit(OpCodes.Call,
            ctor1IL.Emit(OpCodes.Call,71
 typeof(object).GetConstructor(Type.EmptyTypes));
                typeof(object).GetConstructor(Type.EmptyTypes));72
 ctor1IL.Emit(OpCodes.Ldarg_0);
            ctor1IL.Emit(OpCodes.Ldarg_0);73
 ctor1IL.Emit(OpCodes.Ldarg_1);
            ctor1IL.Emit(OpCodes.Ldarg_1);74
 ctor1IL.Emit(OpCodes.Stfld, fbInstance);
            ctor1IL.Emit(OpCodes.Stfld, fbInstance);75
 ctor1IL.Emit(OpCodes.Ret);
            ctor1IL.Emit(OpCodes.Ret);76

77
 foreach (var item in pisInterface)
            foreach (var item in pisInterface)78
 {
            {79
 MethodInfo getMi = FindGetMethodInfo(misImple, item);
                MethodInfo getMi = FindGetMethodInfo(misImple, item);80
 MethodInfo setMi = FindSetMethodInfo(misImple, item);
                MethodInfo setMi = FindSetMethodInfo(misImple, item);81
 CreateProperty(tb, fbInstance, item, getMi, setMi);
                CreateProperty(tb, fbInstance, item, getMi, setMi);82
 }
            }83

84
 foreach (var item in misInterfaceList)
            foreach (var item in misInterfaceList)85
 {
            {86
 MethodInfo instanceMi = FindMethodInfo(misImple, item);
                MethodInfo instanceMi = FindMethodInfo(misImple, item);87
 CreateMethod(tb, fbInstance, item, instanceMi);
                CreateMethod(tb, fbInstance, item, instanceMi);88
 }
            }89
 
            90
 return tb.CreateType();
            return tb.CreateType();91
 }
        }92

93
 private static MethodInfo FindGetMethodInfo(MethodInfo[] miList, PropertyInfo pi)
        private static MethodInfo FindGetMethodInfo(MethodInfo[] miList, PropertyInfo pi)94
 {
        {95
 foreach (var item in miList)
            foreach (var item in miList)96
 {
            {97
 if (item.Name.Equals("get_" + pi.Name) && item.IsSpecialName) return item;
                if (item.Name.Equals("get_" + pi.Name) && item.IsSpecialName) return item;98
 }
            }99

100
 return null;
            return null;101
 }
        }102

103
 private static MethodInfo FindSetMethodInfo(MethodInfo[] miList, PropertyInfo pi)
        private static MethodInfo FindSetMethodInfo(MethodInfo[] miList, PropertyInfo pi)104
 {
        {105
 foreach (var item in miList)
            foreach (var item in miList)106
 {
            {107
 if (item.Name.Equals("set_" + pi.Name) && item.IsSpecialName) return item;
                if (item.Name.Equals("set_" + pi.Name) && item.IsSpecialName) return item;108
 }
            }109
 
            110
 return null;
            return null;111
 }
        }112

113
 private static MethodInfo FindMethodInfo(MethodInfo[] miList, MethodInfo mi)
        private static MethodInfo FindMethodInfo(MethodInfo[] miList, MethodInfo mi)114
 {
        {115
 foreach (var item in miList)
            foreach (var item in miList)116
 {
            {117
 if (MethodInfoEqual(item,mi)) return item;
                if (MethodInfoEqual(item,mi)) return item;118
 }
            }119

120
 return null;
            return null;121
 }
        }122

123
 private static Boolean MethodInfoEqual(MethodInfo mi1, MethodInfo mi2)
        private static Boolean MethodInfoEqual(MethodInfo mi1, MethodInfo mi2)124
 {
        {125
 if (mi1.IsSpecialName == true || mi2.IsSpecialName == true) return false;
            if (mi1.IsSpecialName == true || mi2.IsSpecialName == true) return false;126
 if (mi1.Name != mi2.Name) return false;
            if (mi1.Name != mi2.Name) return false;127
 if (mi1.ReturnType != mi2.ReturnType) return false;
            if (mi1.ReturnType != mi2.ReturnType) return false;128
 ParameterInfo[] pis1 = mi1.GetParameters();
            ParameterInfo[] pis1 = mi1.GetParameters();129
 ParameterInfo[] pis2 = mi2.GetParameters();
            ParameterInfo[] pis2 = mi2.GetParameters();130
 if (pis1.Length != pis2.Length) return false;
            if (pis1.Length != pis2.Length) return false;131
 for (int i = 0; i < pis1.Length; i++)
            for (int i = 0; i < pis1.Length; i++)132
 {
            {133
 ParameterInfo pi1 = pis1[i];
                ParameterInfo pi1 = pis1[i];134
 ParameterInfo pi2 = pis2[i];
                ParameterInfo pi2 = pis2[i];135
 if (pi1.ParameterType != pi2.ParameterType) return false;
                if (pi1.ParameterType != pi2.ParameterType) return false;136
 }
            }137
 return true;
            return true;138
 }
        }139

140
 private static void CreateProperty(TypeBuilder tb, FieldBuilder fbInstance, PropertyInfo pi, MethodInfo getMi, MethodInfo setMi)
        private static void CreateProperty(TypeBuilder tb, FieldBuilder fbInstance, PropertyInfo pi, MethodInfo getMi, MethodInfo setMi)141
 {
        {142
 String name = pi.Name;
            String name = pi.Name;143
 Type type = pi.PropertyType;
            Type type = pi.PropertyType;144

145
 PropertyBuilder pb = tb.DefineProperty(
            PropertyBuilder pb = tb.DefineProperty(146
 name,
                name,147
 PropertyAttributes.HasDefault,
                PropertyAttributes.HasDefault,148
 type,
                type,149
 null);
                null);150

151
 MethodAttributes getSetAttr = MethodAttributes.Public |
            MethodAttributes getSetAttr = MethodAttributes.Public |152
 MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final ;
                MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final ;153
 MethodBuilder mbGetAccessor = tb.DefineMethod(
            MethodBuilder mbGetAccessor = tb.DefineMethod(154
 "get_" + name,
                "get_" + name,155
 getSetAttr,
                getSetAttr,156
 type,
                type,157
 Type.EmptyTypes);
                Type.EmptyTypes);158

159
 ILGenerator getIL = mbGetAccessor.GetILGenerator();
            ILGenerator getIL = mbGetAccessor.GetILGenerator();160
 if (getMi == null)
            if (getMi == null)161
 {
            {162
 getIL.Emit(OpCodes.Newobj, typeof(NotImplementedException).GetConstructor(new Type[]{}));
                getIL.Emit(OpCodes.Newobj, typeof(NotImplementedException).GetConstructor(new Type[]{}));163
 getIL.Emit(OpCodes.Throw);
                getIL.Emit(OpCodes.Throw);164
 }
            }165
 else
            else166
 {
            {167
 getIL.Emit(OpCodes.Ldarg_0);
                getIL.Emit(OpCodes.Ldarg_0);168
 getIL.Emit(OpCodes.Ldfld, fbInstance);
                getIL.Emit(OpCodes.Ldfld, fbInstance);169
 getIL.Emit(OpCodes.Callvirt, getMi);
                getIL.Emit(OpCodes.Callvirt, getMi);170
 getIL.Emit(OpCodes.Ret);
                getIL.Emit(OpCodes.Ret);171
 }
            }172

173
 MethodBuilder mbSetAccessor = tb.DefineMethod(
            MethodBuilder mbSetAccessor = tb.DefineMethod(174
 "set_"+ name,
                "set_"+ name,175
 getSetAttr,
                getSetAttr,176
 null,
                null,177
 new Type[] { type });
                new Type[] { type });178

179
 ILGenerator setIL = mbSetAccessor.GetILGenerator();
            ILGenerator setIL = mbSetAccessor.GetILGenerator();180
 if (setMi == null)
            if (setMi == null)181
 {
            {182
 setIL.Emit(OpCodes.Newobj, typeof(NotImplementedException).GetConstructor(new Type[] { }));
                setIL.Emit(OpCodes.Newobj, typeof(NotImplementedException).GetConstructor(new Type[] { }));183
 setIL.Emit(OpCodes.Throw);
                setIL.Emit(OpCodes.Throw);184
 }
            }185
 else
            else186
 {
            {187
 setIL.Emit(OpCodes.Ldarg_0);
                setIL.Emit(OpCodes.Ldarg_0);188
 setIL.Emit(OpCodes.Ldfld, fbInstance);
                setIL.Emit(OpCodes.Ldfld, fbInstance);189
 setIL.Emit(OpCodes.Ldarg_1);
                setIL.Emit(OpCodes.Ldarg_1);190
 setIL.Emit(OpCodes.Callvirt, setMi);
                setIL.Emit(OpCodes.Callvirt, setMi);191
 setIL.Emit(OpCodes.Ret);
                setIL.Emit(OpCodes.Ret);192
 }
            }193

194
 pb.SetGetMethod(mbGetAccessor);
            pb.SetGetMethod(mbGetAccessor);195
 pb.SetSetMethod(mbSetAccessor);
            pb.SetSetMethod(mbSetAccessor);196
 }
        }197

198
 private static void CreateMethod(TypeBuilder tb, FieldBuilder fbInstance, MethodInfo mi, MethodInfo instanceMi)
        private static void CreateMethod(TypeBuilder tb, FieldBuilder fbInstance, MethodInfo mi, MethodInfo instanceMi)199
 {
        {200
 List<Type> paramTyleList = new List<Type>();
            List<Type> paramTyleList = new List<Type>();201
 foreach(var item in mi.GetParameters())
            foreach(var item in mi.GetParameters())202
 paramTyleList.Add(item.ParameterType);
                paramTyleList.Add(item.ParameterType);203

204
 MethodBuilder mb = tb.DefineMethod(
            MethodBuilder mb = tb.DefineMethod(205
 mi.Name,
              mi.Name,206
 MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final,
              MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final,207
 mi.ReturnType,
              mi.ReturnType,208
 paramTyleList.ToArray());
              paramTyleList.ToArray());209

210
 ILGenerator il = mb.GetILGenerator();
            ILGenerator il = mb.GetILGenerator();211
 if (instanceMi == null)
            if (instanceMi == null)212
 {
            {213
 il.Emit(OpCodes.Newobj, typeof(NotImplementedException).GetConstructor(new Type[] { }));
                il.Emit(OpCodes.Newobj, typeof(NotImplementedException).GetConstructor(new Type[] { }));214
 il.Emit(OpCodes.Throw);
                il.Emit(OpCodes.Throw);215
 }
            }216
 else
            else217
 {
            {218
 il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldarg_0);219
 il.Emit(OpCodes.Ldfld, fbInstance);
                il.Emit(OpCodes.Ldfld, fbInstance);220
 switch (paramTyleList.Count)
                switch (paramTyleList.Count)221
 {
                {222
 case 0:
                    case 0:223
 break;
                        break;224
 case 1:
                    case 1:225
 il.Emit(OpCodes.Ldarg_1);
                        il.Emit(OpCodes.Ldarg_1);226
 break;
                        break;227
 case 2:
                    case 2:228
 il.Emit(OpCodes.Ldarg_1);
                        il.Emit(OpCodes.Ldarg_1);229
 il.Emit(OpCodes.Ldarg_2);
                        il.Emit(OpCodes.Ldarg_2);230
 break;
                        break;231
 case 3:
                    case 3:232
 il.Emit(OpCodes.Ldarg_1);
                        il.Emit(OpCodes.Ldarg_1);233
 il.Emit(OpCodes.Ldarg_2);
                        il.Emit(OpCodes.Ldarg_2);234
 il.Emit(OpCodes.Ldarg_3);
                        il.Emit(OpCodes.Ldarg_3);235
 break;
                        break;236
 default:
                    default:237
 il.Emit(OpCodes.Ldarg_1);
                        il.Emit(OpCodes.Ldarg_1);238
 il.Emit(OpCodes.Ldarg_2);
                        il.Emit(OpCodes.Ldarg_2);239
 il.Emit(OpCodes.Ldarg_3);
                        il.Emit(OpCodes.Ldarg_3);240

241
 Int32 sCount = Math.Min(paramTyleList.Count, 127);
                        Int32 sCount = Math.Min(paramTyleList.Count, 127);242
 for (int i = 4; i <= sCount; i++)
                        for (int i = 4; i <= sCount; i++)243
 {
                        {244
 il.Emit(OpCodes.Ldarg_S, i);
                            il.Emit(OpCodes.Ldarg_S, i);245
 }
                        }246

247
 for (int i = 128; i <= paramTyleList.Count; i++)
                        for (int i = 128; i <= paramTyleList.Count; i++)248
 {
                        {249
 il.Emit(OpCodes.Ldarg, i);
                            il.Emit(OpCodes.Ldarg, i);250
 }
                        }251

252
 break;
                        break;253
 }
                }254

255
 il.Emit(OpCodes.Callvirt, instanceMi);
                il.Emit(OpCodes.Callvirt, instanceMi);256
 il.Emit(OpCodes.Ret);
                il.Emit(OpCodes.Ret);257
 }
            }258
 }
        }259

260
 private static String GetDynamicTypeName<TInterface, TImple>()
        private static String GetDynamicTypeName<TInterface, TImple>()261
 where TInterface : class
            where TInterface : class262
 where TImple : class
            where TImple : class263
 {
        {264
 return "_DynamicTypes" + typeof(TInterface).ToString() + "_" + typeof(TImple);
            return "_DynamicTypes" + typeof(TInterface).ToString() + "_" + typeof(TImple);265
 }
        }266
 }
    }267

268
 public interface TInterface
    public interface TInterface269
 {
    {270
 String A { get; }
        String A { get; }271
 String B(int a, int b);
        String B(int a, int b);272
 }
    }273

274
 public class ClassA
    public class ClassA275
 {
    {276
 public String A
        public String A 277
 {
        {278
 get
            get279
 {
            {280
 return String.Empty;
                return String.Empty;281
 }
            }282
 }
        }283

284
 public String B(int a, int b)
        public String B(int a, int b)285
 {
        {286
 return (a+b).ToString();
            return (a+b).ToString();287
 }
        }288
 }
    }289

290
 public class InterfaceImple_ClassA : TInterface
    public class InterfaceImple_ClassA : TInterface291
 {
    {292
 private ClassA __wrappedInstance;
        private ClassA __wrappedInstance;293

294
 public InterfaceImple_ClassA(ClassA instance)
        public InterfaceImple_ClassA(ClassA instance)295
 {
        {296
 __wrappedInstance = instance;
            __wrappedInstance = instance;297
 }
        }298

299
 public String A
        public String A300
 {
        {301
 get { return __wrappedInstance.A; }
            get { return __wrappedInstance.A; }302
 set { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }303
 }
        }304

305
 public String B(int a, int b)
        public String B(int a, int b)306
 {
        {307
 return __wrappedInstance.B(a,b);
            return __wrappedInstance.B(a,b);308
 }
        }309
 }
    }310

311
 public class InterfaceImple_ClassA_Factory
    public class InterfaceImple_ClassA_Factory312
 {
    {313
 public readonly String Name = "InterfaceImple_ClassA_Factory";
        public readonly String Name = "InterfaceImple_ClassA_Factory";314
 public InterfaceImple_ClassA Create(ClassA a)
        public InterfaceImple_ClassA Create(ClassA a)315
 {
        {316
 return new InterfaceImple_ClassA(a);
            return new InterfaceImple_ClassA(a);317
 }
        }318
 }
    }319
 }
}320

单元测试代码:
 [TestMethod]
        [TestMethod]2
 public void TestCreate()
        public void TestCreate()3
 {
        {4
 ClassA a = new ClassA();
            ClassA a = new ClassA();5
 TInterface i = TypeTemplate.Create<TInterface, ClassA>(a);
            TInterface i = TypeTemplate.Create<TInterface, ClassA>(a);6
 Assert.AreNotEqual(null, i);
            Assert.AreNotEqual(null, i);7
 Assert.AreEqual(String.Empty, i.A);
            Assert.AreEqual(String.Empty, i.A);8
 Assert.AreEqual("3", i.B(1, 2));
            Assert.AreEqual("3", i.B(1, 2));9
 }
        }10

三、说明
1 上文只是 TypeTemplate的原型实现,我只进行了简单的单元测试,没有针对全部可能遇见的情况进行测试;在功能上,未生成event的动态代理;
2 static TInterface Create<TInterface>(TInterface instance, params Object[] impleInstances) 这个方法生成的代理类最好继承一个特殊接口,通过该接口能够接入被代理的实例;
3 如果第一部分所述的三个静态方法全部实现了的话,将是一个非常强大的代理工厂;
4 代理类实例的性能接近于直接调用相关方法或属性的性能,性能极佳;
5 代理类实例的生成是通过反射生成的,在性能上有很大的提升空间。可以通过emit动态生成一个工厂类。如,针对上面的ClassA,生成如下工厂类:
 public class InterfaceImple_ClassA_Factory
    public class InterfaceImple_ClassA_Factory2
 {
    {3
 public readonly String Name = "InterfaceImple_ClassA_Factory";
        public readonly String Name = "InterfaceImple_ClassA_Factory";4
 public InterfaceImple_ClassA Create(ClassA a)
        public InterfaceImple_ClassA Create(ClassA a)5
 {
        {6
 return new InterfaceImple_ClassA(a);
            return new InterfaceImple_ClassA(a);7
 }
        }8
 }
    }9

然后通过反射生成以上工厂类的实例,缓存住。当需要生成新的动态代理实例时,从缓存中查找对应的工厂,生成具体的代理类。
 
                    
                     
                    
                 
                    
                 
    
 String A
        String A  
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号