实现.net下的动态代理 一文使用动态代理实现了 Ducking Typing,解决了文中的第一个问题,下面,向第二个问题进军——mixin。
实现.net下的动态代理 一文使用动态代理实现了 Ducking Typing,解决了文中的第一个问题,下面,向第二个问题进军——mixin。
一、应用场景
(1) 假定有一个接口TInterface,一个类B,类C。类B与类C分别实现了部分TInterface:
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(int a, int b);
5
}
6![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
7
public class ClassB
8![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
9
public String A
10![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
11
get
12![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
13
return String.Empty;
14
}
15
set
16![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{ }
17
}
18
}
19![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
20
public class ClassC
21![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
22
public String B(int a, int b)
23![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.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![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
(2) 通过Mixin,我们还可以在运行时动态替换接口的指定方法或属性:
1
public interface Human
2![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
3
String Heart();
4
String Lung();
5
String Name();
6
}
7![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
8
public class ZhouBapi : Human
9![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
10![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public String Heart()
{ return "好心"; }
11![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public String Lung()
{ return "好肺"; }
12![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public String Name()
{ return "周扒皮"; }
13
}
14![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
15
public class Huaidan
16![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
17![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public String Heart()
{ return "狼心"; }
18![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public String Lung()
{ return "狗肺"; }
19
}
20![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
21
class Program
22![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
23
static void Show(Human body)
24![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
25
Console.WriteLine(String.Format("我叫{0},我是{1}{2}", body.Name(), body.Heart(), body.Lung()));
26
}
27![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
28
static void ShowHuaidan(Human body)
29![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
30
Console.WriteLine(String.Format("{0},我看你是{1}{2}", body.Name(), body.Heart(), body.Lung()));
31
}
32![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
33
static void Main(string[] args)
34![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.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
}
输出为:
周扒皮: 我叫周扒皮,我是好心好肺
人民群众:周扒皮,我看你是狼心狗肺
二、实现
以下是详细实现代码:
![](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)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
9
public sealed class TypeTemplate
10![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
11
public class ObjectContainer
12![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
13
private List<Object> Container = new List<object>();
14
private List<Type> TypeContainer = new List<Type>();
15![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
16
public ObjectContainer(Object[] objs, Type[] tlist)
17![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
18
Container.AddRange(objs);
19
TypeContainer.AddRange(tlist);
20
}
21![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
22
public Object Get(Int32 index)
23![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
24
if (index >= 0 && index < Container.Count)
25
return Container[index];
26
else
27
return null;
28
}
29![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
30
public Type GetType(Int32 index)
31![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
32
if (index >= 0 && index < TypeContainer.Count)
33
return TypeContainer[index];
34
else
35
return null;
36
}
37![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
38
public static MethodInfo GetGetMethodInfo()
39![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
40
MethodInfo[] mis = typeof(ObjectContainer).GetMethods(BindingFlags.Public | BindingFlags.Instance);
41
foreach (var mi in mis)
42![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
43
if (mi.Name == "Get") return mi;
44
}
45
return null;
46
}
47
}
48![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
49
private class MethodInfoHolder
50![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
51![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public Int32 ObjectIndex
{ get; private set; }
52![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public MethodInfo MethodInfo
{ get; private set; }
53![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public Type ObjectType
{ get; private set; }
54
public MethodInfoHolder(MethodInfo pi, Int32 index, Type type)
55![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
56
MethodInfo = pi;
57
ObjectIndex = index;
58
ObjectType = type;
59
}
60
}
61![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
62
public delegate void Handler<TImple>(TImple imple) where TImple: class;
63![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
64
public static TInterface Create<TInterface, TImple>(TImple instance)
65
where TInterface : class
66
where TImple : class
67![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
68![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
Type type = DynamicTypeGen<TInterface>( new Object[]
{ instance }, new Type[]
{ instance.GetType()});
69![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
return Activator.CreateInstance(type, new ObjectContainer(new Object[]
{ instance }, new Type[]
{ instance.GetType() })) as TInterface;
70
}
71![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
72
public static TInterface Create<TInterface>(params Object[] impleInstances)
73
where TInterface : class
74![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
75
List<Type> tlist = new List<Type>();
76
foreach (var item in impleInstances)
77![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.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![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
84
public static TInterface CreateIntercepted<TInterface, TImple>(TImple instance, Handler<TImple> before, Handler<TImple> after)
85
where TInterface : class
86
where TImple : class
87![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
88
throw new NotImplementedException();
89
}
90![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
91
public static Type DynamicTypeGen<TInterface>(Object[] instances, Type[] typeList)
92
where TInterface: class
93![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
94
Type tInterface = typeof(TInterface);
95![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
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)
102![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
103
tList.Add(obj.GetType());
104
}
105![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
106
Type[] tArray = tList.ToArray();
107![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
108
foreach (var item in misInterface)
109![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
110
if (item.IsSpecialName == false) misInterfaceList.Add(item);
111
}
112![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
113
List<MethodInfoHolder> miHolderList = new List<MethodInfoHolder>();
114
for (int i = 0; i < tArray.Length; i++)
115![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
116
MethodInfo[] misImple = tArray[i].GetMethods(BindingFlags.Public | BindingFlags.Instance);
117
foreach (var item in misImple)
118![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
119
MethodInfoHolder h = new MethodInfoHolder(item, i, typeList[i]);
120
miHolderList.Add(h);
121
}
122
}
123![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
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![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
133
TypeBuilder tb = mb.DefineType(GetDynamicTypeName<TInterface>(instances),
134![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
TypeAttributes.Public, null, new Type[]
{ tInterface });
135
FieldBuilder fbInstances = tb.DefineField(
136
"_container",
137
typeof(TypeTemplate.ObjectContainer),
138
FieldAttributes.Private);
139![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
140
ConstructorBuilder ctor1 = tb.DefineConstructor(
141
MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.RTSpecialName,
142
CallingConventions.Standard,
143![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
new Type[1]
{ typeof(TypeTemplate.ObjectContainer) });
144![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
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![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
153
foreach (var item in pisInterface)
154![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
155
MethodInfoHolder getMi = FindGetMethodInfo(miHolderList, item);
156
MethodInfoHolder setMi = FindSetMethodInfo(miHolderList, item);
157
CreateProperty(tb, fbInstances, item, getMi, setMi);
158
}
159![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
160
foreach (var item in misInterfaceList)
161![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.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![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
170
private static MethodInfoHolder FindGetMethodInfo(IEnumerable<MethodInfoHolder> miList, PropertyInfo pi)
171![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
172
foreach (var item in miList)
173![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
174
if (item.MethodInfo.Name.Equals("get_" + pi.Name) && item.MethodInfo.IsSpecialName) return item;
175
}
176![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
177
return null;
178
}
179![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
180
private static MethodInfoHolder FindSetMethodInfo(IEnumerable<MethodInfoHolder> miList, PropertyInfo pi)
181![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
182
foreach (var item in miList)
183![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
184
if (item.MethodInfo.Name.Equals("set_" + pi.Name) && item.MethodInfo.IsSpecialName) return item;
185
}
186
187
return null;
188
}
189![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
190
private static MethodInfoHolder FindMethodInfo(IEnumerable<MethodInfoHolder> miList, MethodInfo mi)
191![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
192
foreach (var item in miList)
193![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
194
if (MethodInfoEqual(item.MethodInfo,mi)) return item;
195
}
196![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
197
return null;
198
}
199![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
200
private static Boolean MethodInfoEqual(MethodInfo mi1, MethodInfo mi2)
201![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
202
if (mi1.IsSpecialName == true || mi2.IsSpecialName == true) return 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++)
209![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.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![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
217
private static void CreateProperty(TypeBuilder tb, FieldBuilder fbInstance, PropertyInfo pi, MethodInfoHolder getMi, MethodInfoHolder setMi)
218![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
219
String name = pi.Name;
220
Type type = pi.PropertyType;
221![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
222
PropertyBuilder pb = tb.DefineProperty(
223
name,
224
PropertyAttributes.HasDefault,
225
type,
226
null);
227![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
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![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
236
ILGenerator getIL = mbGetAccessor.GetILGenerator();
237
238
if (getMi == null)
239![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
240![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
getIL.Emit(OpCodes.Newobj, typeof(NotImplementedException).GetConstructor(new Type[]
{}));
241
getIL.Emit(OpCodes.Throw);
242
}
243
else
244![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.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![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
254
MethodBuilder mbSetAccessor = tb.DefineMethod(
255
"set_"+ name,
256
getSetAttr,
257
null,
258![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
new Type[]
{ type });
259![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
260
ILGenerator setIL = mbSetAccessor.GetILGenerator();
261
if (setMi == null)
262![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
263![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
setIL.Emit(OpCodes.Newobj, typeof(NotImplementedException).GetConstructor(new Type[]
{ }));
264
setIL.Emit(OpCodes.Throw);
265
}
266
else
267![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.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![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
278
pb.SetGetMethod(mbGetAccessor);
279
pb.SetSetMethod(mbSetAccessor);
280
}
281![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
282
private static void CreateMethod(TypeBuilder tb, FieldBuilder fbInstance, MethodInfo mi, MethodInfoHolder instanceMi)
283![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
284
List<Type> paramTyleList = new List<Type>();
285
foreach(var item in mi.GetParameters())
286
paramTyleList.Add(item.ParameterType);
287![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
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![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
294
ILGenerator il = mb.GetILGenerator();
295
if (instanceMi == null)
296![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
297![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
il.Emit(OpCodes.Newobj, typeof(NotImplementedException).GetConstructor(new Type[]
{ }));
298
il.Emit(OpCodes.Throw);
299
}
300
else
301![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.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)
308![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.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![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
328
Int32 sCount = Math.Min(paramTyleList.Count, 127);
329
for (int i = 4; i <= sCount; i++)
330![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
331
il.Emit(OpCodes.Ldarg_S, i);
332
}
333![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
334
for (int i = 128; i <= paramTyleList.Count; i++)
335![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
336
il.Emit(OpCodes.Ldarg, i);
337
}
338![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
339
break;
340
}
341![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
342
il.Emit(OpCodes.Callvirt, instanceMi.MethodInfo);
343
il.Emit(OpCodes.Ret);
344
}
345
}
346![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
347
private static String GetDynamicTypeName<TInterface>(params Object[] instances)
348
where TInterface : class
349![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
350
StringBuilder sb = new StringBuilder();
351
sb.Append("_DynamicTypes");
352
sb.Append(typeof(TInterface).ToString());
353
foreach (var obj in instances)
354![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
355
sb.Append("_");
356
sb.Append(obj.GetType().ToString());
357
}
358
return sb.ToString();
359
}
360
}
361![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
362
public interface TInterface
363![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
364![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
String A
{ get; }
365
String B(int a, int b);
366
}
367![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
368
public class ClassB
369![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
370
public String A
371![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
372
get
373![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
374
return String.Empty;
375
}
376
set
377![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{ }
378
}
379
}
380![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
381
public class ClassC
382![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
383
public String B(int a, int b)
384![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
385
return (a + b).ToString();
386
}
387
}
388![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
389
public class ClassA
390![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
391
public String A
392![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
393
get
394![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
395
return String.Empty;
396
}
397
set
398![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{ }
399
}
400![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
401
public String B(int a, int b)
402![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
403
return (a+b).ToString();
404
}
405
}
406![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
407
public class InterfaceImple_ClassA : TInterface
408![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
409
private TypeTemplate.ObjectContainer __container;
410![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
411
public InterfaceImple_ClassA(TypeTemplate.ObjectContainer container)
412![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
413
__container = container;
414
}
415![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
416
public String A
417![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
418![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
get
{ return (__container.Get(1) as ClassA).A; }
419![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
set
{ (__container.Get(1) as ClassA).A = value; }
420
}
421![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
422
public String B(int a, int b)
423![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
424
return (__container.Get(1) as ClassA).B(a, b);
425
}
426
}
427![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
428
public class InterfaceImple_ClassA_Factory
429![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
430
public readonly String Name = "InterfaceImple_ClassA_Factory";
431
public InterfaceImple_ClassA Create(ClassA a)
432![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
433
return null;
434
// return new InterfaceImple_ClassA(new Object[] {a});
435
}
436
}
437
}
438![](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 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![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
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![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
三、说明:
(1)通过上述方法可以很方便的创建对现有实例的Wrapper,使其适应一个新的接口;
(2)TypeTemplate.Create<TInterface>(params Object[] impleInstances) 排位在前的 impleInstance 的接口方法/属性将掩盖它后面的 impleInstance 的接口方法/属性,这样可以在运行时动态改变接口的行为。
(3)这种MixIn方案比不上动态语言的MixIn,主要是必须要有一个interface,才能MixIn。如果能将interface也根据被代理的对象的行为动态生成,那就很爽了。怎么实现,是一个问题。