一、动态代理可以解决哪些问题
本文描述的动态代理可以解决以下问题:
问题1:接口约束问题
场景A:ComboBox类与ToolStripComboBox类的行为大部分相似,它们却不共享某个粒度较大的接口,以至于对这两个类的操作代码难以公用。
场景B:在泛型程序中,我们必需为泛型类型声明一个接口约束,才能使用该类型所对应接口约束的方法与属性。这样以来有一个问题:存在接口A,类型B,A中的所有属性和方法签名B都有,但B不是A的实现,不能由B转换为A。而由于某些原因,我们无法获得B的代码或者虽然能够获得B的代码,却由于种种考虑不能更改B的代码;
大多数情况下,可以新写一个类C,使类C继承自B,再让C实现接口A。然而,其一,代码量较大;其二,当B为Sealed时不能继承;其三:不方便使用继承(如:继承后,IDE中的设计器无法给新类提供支持)。
此时,我们希望动态代理能解决这个问题:
假定我们有一个接口:
1
public interface TInterface
2![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
3![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
String A { get; }
4
String B(Object a, Object b, Object c, Object d, Object e);
5
}
6![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
有一个类:
1
public class ClassA
2![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
3
public String A
4![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
5
get
6![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
7
return String.Empty;
8
}
9
}
10![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
11
public String B(Object a, Object b, Object c, Object d, Object e)
12![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
13
return String.Empty;
14
}
15
}
16![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
17![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
我们需要这个动态代理类(假定为 TypeTemplate)提供一个方法,能够方便的生成一个代理类实例,将ClassA的实例包装一下,转变为 TInterface 的实例:
1
public static TInterface Create<TInterface, TImple>(TImple instance)
2
where TInterface : class
3
where TImple : class
4![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
5
……
6
}
7![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
该方法生成一个实现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能够提供以下方法:
1
public static TInterface Create<TInterface>(TInterface instance, params Object[] impleInstances)
2
where TInterface : class
3![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
4
…
5
}
6![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
该方法生成一个实现TInterface的类实例。对于TInterface中的每一个属性或方法,该实例依次从impleInstances中寻找具有同样签名的属性或方法,如果没有匹配的属性或方法,则抛出NotImplementedException异常。
问题3:AOP应用
场景D:当需要对方法进行拦截时我们需要动态代理。
AOP是动态代理最经典的应用,无需赘述。
这种情况下,我们需要 TypeTemplate 类提供以下的方法向代理类中加入钩子:
1
public delegate void Handler<TImple>(TImple imple) where TImple: class;
2![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
3
public static TInterface CreateIntercepted<TInterface, TImple>(TImple instance, Handler<TImple> before, Handler<TImple> after)
4
where TInterface : class
5
where TImple : class
6![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
7
…
8
}
9![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
二、实现
下面来实现动态代理类工厂TypeTemplate。由于时间有限,只实现 static TInterface Create<TInterface, TImple>(TImple instance) 方法原型。其它几个静态方法可以用类似的方式实现。
实现思路:
对于问题1中的接口TInterface和类ClassA,通过Emit生成如下类型InterfaceImple_ClassA的IL代码。
1
public class InterfaceImple_ClassA : TInterface
2![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
3
private ClassA __wrappedInstance;
4![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
5
public InterfaceImple_ClassA(ClassA instance)
6![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
7
__wrappedInstance = instance;
8
}
9![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
10
public String A
11![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
12![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get { return __wrappedInstance.A; }
13![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set { throw new NotImplementedException(); }
14
}
15![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
16
public String B(Object a, Object b, Object c, Object d, Object e)
17![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
18
return __wrappedInstance.B(a,b,c,d,e);
19
}
20
}
21![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
22![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
假定生成上面这个类型的方法为:
1
public static Type DynamicTypeGen<TInterface, TImple>()
2
where TInterface: class where TImple : class
3![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
4![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
则可用Activator轻松生成动态代理类实例:
1
public static TInterface Create<TInterface, TImple>(TImple instance)
2
where TInterface : class
3
where TImple : class
4![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
5
Type type = DynamicTypeGen<TInterface, TImple>();
6
return Activator.CreateInstance(type, instance) as TInterface;
7
}
8![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
下面是具体代码:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.Reflection;
5
using System.Reflection.Emit;
6![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
7
namespace Orc.Generics
8![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
9
public sealed class TypeTemplate
10![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
11
public delegate void Handler<TImple>(TImple imple) where TImple: class;
12![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
13
public static TInterface Create<TInterface, TImple>(TImple instance)
14
where TInterface : class
15
where TImple : class
16![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
17
Type type = DynamicTypeGen<TInterface, TImple>();
18
return Activator.CreateInstance(type, instance) as TInterface;
19
}
20![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
21
public static TInterface Create<TInterface>(TInterface instance, params Object[] impleInstances)
22
where TInterface : class
23![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
24
throw new NotImplementedException();
25
}
26![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
27
public static TInterface CreateIntercepted<TInterface, TImple>(TImple instance, Handler<TImple> before, Handler<TImple> after)
28
where TInterface : class
29
where TImple : class
30![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
31
throw new NotImplementedException();
32
}
33![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
34
public static Type DynamicTypeGen<TInterface, TImple>()
35
where TInterface: class where TImple : class
36![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
37
Type tInterface = typeof(TInterface);
38
Type tImple = typeof(TImple);
39![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
40
PropertyInfo[] pisInterface = tInterface.GetProperties(BindingFlags.Public | BindingFlags.Instance);
41
MethodInfo[] misInterface = tInterface.GetMethods(BindingFlags.Public | BindingFlags.Instance);
42
List<MethodInfo> misInterfaceList = new List<MethodInfo>();
43
foreach (var item in misInterface)
44![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
45
if (item.IsSpecialName == false) misInterfaceList.Add(item);
46
}
47![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
48
MethodInfo[] misImple = tImple.GetMethods(BindingFlags.Public | BindingFlags.Instance);
49
AssemblyName aName = new AssemblyName("Orc.Generics.DynamicTypes");
50
AssemblyBuilder ab =
51
AppDomain.CurrentDomain.DefineDynamicAssembly(
52
aName,
53
AssemblyBuilderAccess.RunAndSave);
54
ModuleBuilder mb =
55
ab.DefineDynamicModule(aName.Name, aName.Name + ".dll");
56
TypeBuilder tb = mb.DefineType(GetDynamicTypeName<TInterface, TImple>(),
57![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
TypeAttributes.Public, null, new Type[] { tInterface });
58
FieldBuilder fbInstance = tb.DefineField(
59
"__wrappedInstance",
60
tImple,
61
FieldAttributes.Private);
62![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
63
ConstructorBuilder ctor1 = tb.DefineConstructor(
64
MethodAttributes.Public,
65
CallingConventions.Standard,
66![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
new Type[] {tImple});
67![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
68
ILGenerator ctor1IL = ctor1.GetILGenerator();
69
ctor1IL.Emit(OpCodes.Ldarg_0);
70
ctor1IL.Emit(OpCodes.Call,
71
typeof(object).GetConstructor(Type.EmptyTypes));
72
ctor1IL.Emit(OpCodes.Ldarg_0);
73
ctor1IL.Emit(OpCodes.Ldarg_1);
74
ctor1IL.Emit(OpCodes.Stfld, fbInstance);
75
ctor1IL.Emit(OpCodes.Ret);
76![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
77
foreach (var item in pisInterface)
78![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
79
MethodInfo getMi = FindGetMethodInfo(misImple, item);
80
MethodInfo setMi = FindSetMethodInfo(misImple, item);
81
CreateProperty(tb, fbInstance, item, getMi, setMi);
82
}
83![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
84
foreach (var item in misInterfaceList)
85![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
86
MethodInfo instanceMi = FindMethodInfo(misImple, item);
87
CreateMethod(tb, fbInstance, item, instanceMi);
88
}
89
90
return tb.CreateType();
91
}
92![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
93
private static MethodInfo FindGetMethodInfo(MethodInfo[] miList, PropertyInfo pi)
94![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
95
foreach (var item in miList)
96![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
97
if (item.Name.Equals("get_" + pi.Name) && item.IsSpecialName) return item;
98
}
99![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
100
return null;
101
}
102![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
103
private static MethodInfo FindSetMethodInfo(MethodInfo[] miList, PropertyInfo pi)
104![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
105
foreach (var item in miList)
106![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
107
if (item.Name.Equals("set_" + pi.Name) && item.IsSpecialName) return item;
108
}
109
110
return null;
111
}
112![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
113
private static MethodInfo FindMethodInfo(MethodInfo[] miList, MethodInfo mi)
114![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
115
foreach (var item in miList)
116![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
117
if (MethodInfoEqual(item,mi)) return item;
118
}
119![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
120
return null;
121
}
122![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
123
private static Boolean MethodInfoEqual(MethodInfo mi1, MethodInfo mi2)
124![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
125
if (mi1.IsSpecialName == true || mi2.IsSpecialName == true) return false;
126
if (mi1.Name != mi2.Name) return false;
127
if (mi1.ReturnType != mi2.ReturnType) return false;
128
ParameterInfo[] pis1 = mi1.GetParameters();
129
ParameterInfo[] pis2 = mi2.GetParameters();
130
if (pis1.Length != pis2.Length) return false;
131
for (int i = 0; i < pis1.Length; i++)
132![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
133
ParameterInfo pi1 = pis1[i];
134
ParameterInfo pi2 = pis2[i];
135
if (pi1.ParameterType != pi2.ParameterType) return false;
136
}
137
return true;
138
}
139![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
140
private static void CreateProperty(TypeBuilder tb, FieldBuilder fbInstance, PropertyInfo pi, MethodInfo getMi, MethodInfo setMi)
141![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
142
String name = pi.Name;
143
Type type = pi.PropertyType;
144![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
145
PropertyBuilder pb = tb.DefineProperty(
146
name,
147
PropertyAttributes.HasDefault,
148
type,
149
null);
150![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
151
MethodAttributes getSetAttr = MethodAttributes.Public |
152
MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final ;
153
MethodBuilder mbGetAccessor = tb.DefineMethod(
154
"get_" + name,
155
getSetAttr,
156
type,
157
Type.EmptyTypes);
158![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
159
ILGenerator getIL = mbGetAccessor.GetILGenerator();
160
if (getMi == null)
161![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
162![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
getIL.Emit(OpCodes.Newobj, typeof(NotImplementedException).GetConstructor(new Type[]{}));
163
getIL.Emit(OpCodes.Throw);
164
}
165
else
166![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
167
getIL.Emit(OpCodes.Ldarg_0);
168
getIL.Emit(OpCodes.Ldfld, fbInstance);
169
getIL.Emit(OpCodes.Callvirt, getMi);
170
getIL.Emit(OpCodes.Ret);
171
}
172![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
173
MethodBuilder mbSetAccessor = tb.DefineMethod(
174
"set_"+ name,
175
getSetAttr,
176
null,
177![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
new Type[] { type });
178![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
179
ILGenerator setIL = mbSetAccessor.GetILGenerator();
180
if (setMi == null)
181![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
182![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
setIL.Emit(OpCodes.Newobj, typeof(NotImplementedException).GetConstructor(new Type[] { }));
183
setIL.Emit(OpCodes.Throw);
184
}
185
else
186![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
187
setIL.Emit(OpCodes.Ldarg_0);
188
setIL.Emit(OpCodes.Ldfld, fbInstance);
189
setIL.Emit(OpCodes.Ldarg_1);
190
setIL.Emit(OpCodes.Callvirt, setMi);
191
setIL.Emit(OpCodes.Ret);
192
}
193![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
194
pb.SetGetMethod(mbGetAccessor);
195
pb.SetSetMethod(mbSetAccessor);
196
}
197![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
198
private static void CreateMethod(TypeBuilder tb, FieldBuilder fbInstance, MethodInfo mi, MethodInfo instanceMi)
199![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
200
List<Type> paramTyleList = new List<Type>();
201
foreach(var item in mi.GetParameters())
202
paramTyleList.Add(item.ParameterType);
203![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
204
MethodBuilder mb = tb.DefineMethod(
205
mi.Name,
206
MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual | MethodAttributes.Final,
207
mi.ReturnType,
208
paramTyleList.ToArray());
209![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
210
ILGenerator il = mb.GetILGenerator();
211
if (instanceMi == null)
212![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
213![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
il.Emit(OpCodes.Newobj, typeof(NotImplementedException).GetConstructor(new Type[] { }));
214
il.Emit(OpCodes.Throw);
215
}
216
else
217![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
218
il.Emit(OpCodes.Ldarg_0);
219
il.Emit(OpCodes.Ldfld, fbInstance);
220
switch (paramTyleList.Count)
221![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
222
case 0:
223
break;
224
case 1:
225
il.Emit(OpCodes.Ldarg_1);
226
break;
227
case 2:
228
il.Emit(OpCodes.Ldarg_1);
229
il.Emit(OpCodes.Ldarg_2);
230
break;
231
case 3:
232
il.Emit(OpCodes.Ldarg_1);
233
il.Emit(OpCodes.Ldarg_2);
234
il.Emit(OpCodes.Ldarg_3);
235
break;
236
default:
237
il.Emit(OpCodes.Ldarg_1);
238
il.Emit(OpCodes.Ldarg_2);
239
il.Emit(OpCodes.Ldarg_3);
240![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
241
Int32 sCount = Math.Min(paramTyleList.Count, 127);
242
for (int i = 4; i <= sCount; i++)
243![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
244
il.Emit(OpCodes.Ldarg_S, i);
245
}
246![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
247
for (int i = 128; i <= paramTyleList.Count; i++)
248![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
249
il.Emit(OpCodes.Ldarg, i);
250
}
251![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
252
break;
253
}
254![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
255
il.Emit(OpCodes.Callvirt, instanceMi);
256
il.Emit(OpCodes.Ret);
257
}
258
}
259![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
260
private static String GetDynamicTypeName<TInterface, TImple>()
261
where TInterface : class
262
where TImple : class
263![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
264
return "_DynamicTypes" + typeof(TInterface).ToString() + "_" + typeof(TImple);
265
}
266
}
267![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
268
public interface TInterface
269![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
270![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
String A { get; }
271
String B(int a, int b);
272
}
273![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
274
public class ClassA
275![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
276
public String A
277![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
278
get
279![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
280
return String.Empty;
281
}
282
}
283![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
284
public String B(int a, int b)
285![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
286
return (a+b).ToString();
287
}
288
}
289![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
290
public class InterfaceImple_ClassA : TInterface
291![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
292
private ClassA __wrappedInstance;
293![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
294
public InterfaceImple_ClassA(ClassA instance)
295![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
296
__wrappedInstance = instance;
297
}
298![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
299
public String A
300![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
301![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get { return __wrappedInstance.A; }
302![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set { throw new NotImplementedException(); }
303
}
304![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
305
public String B(int a, int b)
306![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
307
return __wrappedInstance.B(a,b);
308
}
309
}
310![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
311
public class InterfaceImple_ClassA_Factory
312![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
313
public readonly String Name = "InterfaceImple_ClassA_Factory";
314
public InterfaceImple_ClassA Create(ClassA a)
315![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
316
return new InterfaceImple_ClassA(a);
317
}
318
}
319
}
320![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
单元测试代码:
1
[TestMethod]
2
public void TestCreate()
3![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
4
ClassA a = new ClassA();
5
TInterface i = TypeTemplate.Create<TInterface, ClassA>(a);
6
Assert.AreNotEqual(null, i);
7
Assert.AreEqual(String.Empty, i.A);
8
Assert.AreEqual("3", i.B(1, 2));
9
}
10![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
三、说明
1 上文只是 TypeTemplate的原型实现,我只进行了简单的单元测试,没有针对全部可能遇见的情况进行测试;在功能上,未生成event的动态代理;
2 static TInterface Create<TInterface>(TInterface instance, params Object[] impleInstances) 这个方法生成的代理类最好继承一个特殊接口,通过该接口能够接入被代理的实例;
3 如果第一部分所述的三个静态方法全部实现了的话,将是一个非常强大的代理工厂;
4 代理类实例的性能接近于直接调用相关方法或属性的性能,性能极佳;
5 代理类实例的生成是通过反射生成的,在性能上有很大的提升空间。可以通过emit动态生成一个工厂类。如,针对上面的ClassA,生成如下工厂类:
1
public class InterfaceImple_ClassA_Factory
2![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
3
public readonly String Name = "InterfaceImple_ClassA_Factory";
4
public InterfaceImple_ClassA Create(ClassA a)
5![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
6
return new InterfaceImple_ClassA(a);
7
}
8
}
9![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
然后通过反射生成以上工厂类的实例,缓存住。当需要生成新的动态代理实例时,从缓存中查找对应的工厂,生成具体的代理类。
转自:http://www.cnblogs.com/xiaotie/archive/2009/02/01/1381825.html
好文