forked from philiplaureano/LinFu.DynamicProxy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ProxyFactory.cs
359 lines (284 loc) · 14.4 KB
/
ProxyFactory.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.Serialization;
namespace LinFu.DynamicProxy
{
public class ProxyFactory
{
private static readonly ConstructorInfo baseConstructor = typeof(object).GetConstructor(new Type[0]);
private static readonly MethodInfo getTypeFromHandle = typeof(Type).GetMethod("GetTypeFromHandle");
#if !SILVERLIGHT
private static readonly MethodInfo getValue = typeof(SerializationInfo).GetMethod("GetValue", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(string), typeof(Type) }, null);
private static readonly MethodInfo setType = typeof(SerializationInfo).GetMethod("SetType", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(Type) }, null);
private static readonly MethodInfo addValue = typeof(SerializationInfo).GetMethod("AddValue", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(string), typeof(object) }, null);
#endif
private IProxyCache _cache = new ProxyCache();
private IProxyMethodBuilder _proxyMethodBuilder;
public ProxyFactory()
: this(new DefaultyProxyMethodBuilder())
{
}
public ProxyFactory(IProxyMethodBuilder proxyMethodBuilder)
{
_proxyMethodBuilder = proxyMethodBuilder;
}
public IProxyCache Cache
{
get { return _cache; }
set { _cache = value; }
}
public IProxyMethodBuilder ProxyMethodBuilder
{
get { return _proxyMethodBuilder; }
set { _proxyMethodBuilder = value; }
}
public virtual object CreateProxy(Type instanceType, IInvokeWrapper wrapper, params Type[] baseInterfaces)
{
return CreateProxy(instanceType, new CallAdapter(wrapper), baseInterfaces);
}
public virtual object CreateProxy(Type instanceType, IInterceptor interceptor, params Type[] baseInterfaces)
{
Type proxyType = CreateProxyType(instanceType, baseInterfaces);
object result = Activator.CreateInstance(proxyType);
IProxy proxy = (IProxy)result;
proxy.Interceptor = interceptor;
return result;
}
public virtual T CreateProxy<T>(IInvokeWrapper wrapper, params Type[] baseInterfaces)
{
return CreateProxy<T>(new CallAdapter(wrapper), baseInterfaces);
}
public virtual T CreateProxy<T>(IInterceptor interceptor, params Type[] baseInterfaces)
{
Type proxyType = CreateProxyType(typeof(T), baseInterfaces);
T result = (T)Activator.CreateInstance(proxyType);
Debug.Assert(result != null);
IProxy proxy = (IProxy)result;
proxy.Interceptor = interceptor;
return result;
}
public virtual Type CreateProxyType(Type baseType, params Type[] baseInterfaces)
{
// Reuse the previous results, if possible
if (_cache != null && _cache.Contains(baseType, baseInterfaces))
return _cache.GetProxyType(baseType, baseInterfaces);
Type result = CreateUncachedProxyType(baseInterfaces, baseType);
// Cache the proxy type
if (result != null && _cache != null)
_cache.StoreProxyType(result, baseType, baseInterfaces);
return result;
}
private Type CreateUncachedProxyType(Type[] baseInterfaces, Type baseType)
{
AppDomain currentDomain = AppDomain.CurrentDomain;
string typeName = string.Format("{0}Proxy", baseType.Name);
string assemblyName = string.Format("{0}Assembly", typeName);
string moduleName = string.Format("{0}Module", typeName);
AssemblyName name = new AssemblyName(assemblyName);
#if DEBUG && !SILVERLIGHT
AssemblyBuilderAccess access = AssemblyBuilderAccess.RunAndSave;
#else
AssemblyBuilderAccess access = AssemblyBuilderAccess.Run;
#endif
AssemblyBuilder assemblyBuilder = currentDomain.DefineDynamicAssembly(name, access);
#if DEBUG && !SILVERLIGHT
ModuleBuilder moduleBuilder =
assemblyBuilder.DefineDynamicModule(moduleName, string.Format("{0}.mod", moduleName), true);
#else
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(moduleName);
#endif
TypeAttributes typeAttributes = TypeAttributes.AutoClass | TypeAttributes.Class |
TypeAttributes.Public | TypeAttributes.BeforeFieldInit;
List<Type> interfaceList = new List<Type>();
if (baseInterfaces != null && baseInterfaces.Length > 0)
interfaceList.AddRange(baseInterfaces);
// Use the proxy dummy as the base type
// since we're not inheriting from any class type
Type parentType = baseType;
if (baseType.IsInterface)
{
parentType = typeof(ProxyDummy);
interfaceList.Add(baseType);
}
// Add any inherited interfaces
Type[] interfaces = interfaceList.ToArray();
foreach (Type interfaceType in interfaces)
{
BuildInterfaceList(interfaceType, interfaceList);
}
#if !SILVERLIGHT
// Add the ISerializable interface so that it can be implemented
if (!interfaceList.Contains(typeof(ISerializable)))
interfaceList.Add(typeof(ISerializable));
#endif
TypeBuilder typeBuilder =
moduleBuilder.DefineType(typeName, typeAttributes, parentType, interfaceList.ToArray());
ConstructorBuilder defaultConstructor = DefineConstructor(typeBuilder);
// Implement IProxy
ProxyImplementor implementor = new ProxyImplementor();
implementor.ImplementProxy(typeBuilder);
MethodInfo[] methods = baseType.GetMethods(BindingFlags.Public | BindingFlags.Instance);
List<MethodInfo> proxyList = new List<MethodInfo>();
BuildMethodList(interfaceList, methods, proxyList);
Debug.Assert(_proxyMethodBuilder != null, "ProxyMethodBuilder cannot be null");
FieldInfo interceptorField = implementor.InterceptorField;
foreach (MethodInfo method in proxyList)
{
#if !SILVERLIGHT
// Provide a custom implementation of ISerializable
// instead of redirecting it back to the interceptor
if (method.DeclaringType == typeof(ISerializable))
continue;
#endif
_proxyMethodBuilder.CreateProxiedMethod(interceptorField, method, typeBuilder);
}
#if !SILVERLIGHT
// Make the proxy serializable
AddSerializationSupport(baseType, baseInterfaces, typeBuilder, interceptorField, defaultConstructor);
#endif
Type proxyType = typeBuilder.CreateType();
#if DEBUG_PROXY_OUTPUT
assemblyBuilder.Save("generatedAssembly.dll");
#endif
return proxyType;
}
private static void BuildInterfaceList(Type currentType, List<Type> interfaceList)
{
Type[] interfaces = currentType.GetInterfaces();
if (interfaces == null || interfaces.Length == 0)
return;
foreach (Type current in interfaces)
{
if (interfaceList.Contains(current))
continue;
interfaceList.Add(current);
BuildInterfaceList(current, interfaceList);
}
}
private static void BuildMethodList(IEnumerable<Type> interfaceList, IEnumerable<MethodInfo> methods,
List<MethodInfo> proxyList)
{
foreach (MethodInfo method in methods)
{
//if (method.DeclaringType == typeof(object))
// continue;
// Only non-private methods will be proxied
if (method.IsPrivate)
continue;
// Final methods cannot be overridden
if (method.IsFinal)
continue;
// Only virtual methods can be intercepted
if (!method.IsVirtual && !method.IsAbstract)
continue;
proxyList.Add(method);
}
foreach (Type interfaceType in interfaceList)
{
MethodInfo[] interfaceMethods = interfaceType.GetMethods();
foreach (MethodInfo interfaceMethod in interfaceMethods)
{
if (proxyList.Contains(interfaceMethod))
continue;
proxyList.Add(interfaceMethod);
}
}
}
private static ConstructorBuilder DefineConstructor(TypeBuilder typeBuilder)
{
MethodAttributes constructorAttributes = MethodAttributes.Public |
MethodAttributes.HideBySig | MethodAttributes.SpecialName |
MethodAttributes.RTSpecialName;
ConstructorBuilder constructor =
typeBuilder.DefineConstructor(constructorAttributes, CallingConventions.Standard, new Type[] { });
ILGenerator IL = constructor.GetILGenerator();
constructor.SetImplementationFlags(MethodImplAttributes.IL | MethodImplAttributes.Managed);
IL.Emit(OpCodes.Ldarg_0);
IL.Emit(OpCodes.Call, baseConstructor);
IL.Emit(OpCodes.Ret);
return constructor;
}
#if !SILVERLIGHT
private static void ImplementGetObjectData(Type baseType, Type[] baseInterfaces, TypeBuilder typeBuilder, FieldInfo interceptorField)
{
MethodAttributes attributes = MethodAttributes.Public | MethodAttributes.HideBySig |
MethodAttributes.Virtual;
Type[] parameterTypes = new Type[] { typeof(SerializationInfo), typeof(StreamingContext) };
MethodBuilder methodBuilder =
typeBuilder.DefineMethod("GetObjectData", attributes, typeof(void), parameterTypes);
ILGenerator IL = methodBuilder.GetILGenerator();
//LocalBuilder proxyBaseType = IL.DeclareLocal(typeof(Type));
// info.SetType(typeof(ProxyObjectReference));
IL.Emit(OpCodes.Ldarg_1);
IL.Emit(OpCodes.Ldtoken, typeof(ProxyObjectReference));
IL.Emit(OpCodes.Call, getTypeFromHandle);
IL.Emit(OpCodes.Callvirt, setType);
// info.AddValue("__interceptor", __interceptor);
IL.Emit(OpCodes.Ldarg_1);
IL.Emit(OpCodes.Ldstr, "__interceptor");
IL.Emit(OpCodes.Ldarg_0);
IL.Emit(OpCodes.Ldfld, interceptorField);
IL.Emit(OpCodes.Callvirt, addValue);
IL.Emit(OpCodes.Ldarg_1);
IL.Emit(OpCodes.Ldstr, "__baseType");
IL.Emit(OpCodes.Ldstr, baseType.AssemblyQualifiedName);
IL.Emit(OpCodes.Callvirt, addValue);
var interfaces = baseInterfaces ?? new Type[0];
int baseInterfaceCount = interfaces.Length;
// Save the number of base interfaces
IL.Emit(OpCodes.Ldarg_1);
IL.Emit(OpCodes.Ldstr, "__baseInterfaceCount");
IL.Emit(OpCodes.Ldc_I4, baseInterfaceCount);
IL.Emit(OpCodes.Box, typeof(Int32));
IL.Emit(OpCodes.Callvirt, addValue);
int index = 0;
foreach (Type baseInterface in interfaces)
{
IL.Emit(OpCodes.Ldarg_1);
IL.Emit(OpCodes.Ldstr, string.Format("__baseInterface{0}", index++));
IL.Emit(OpCodes.Ldstr, baseInterface.AssemblyQualifiedName);
IL.Emit(OpCodes.Callvirt, addValue);
}
IL.Emit(OpCodes.Ret);
}
private static void DefineSerializationConstructor(Type[] baseInterfaces, TypeBuilder typeBuilder, FieldInfo interceptorField, ConstructorBuilder defaultConstructor)
{
MethodAttributes constructorAttributes = MethodAttributes.Public |
MethodAttributes.HideBySig | MethodAttributes.SpecialName |
MethodAttributes.RTSpecialName;
Type[] parameterTypes = new Type[] { typeof(SerializationInfo), typeof(StreamingContext) };
ConstructorBuilder constructor = typeBuilder.DefineConstructor(constructorAttributes,
CallingConventions.Standard, parameterTypes);
ILGenerator IL = constructor.GetILGenerator();
LocalBuilder interceptorType = IL.DeclareLocal(typeof(Type));
//LocalBuilder interceptor = IL.DeclareLocal(typeof(IInterceptor));
constructor.SetImplementationFlags(MethodImplAttributes.IL | MethodImplAttributes.Managed);
IL.Emit(OpCodes.Ldtoken, typeof(IInterceptor));
IL.Emit(OpCodes.Call, getTypeFromHandle);
IL.Emit(OpCodes.Stloc, interceptorType);
IL.Emit(OpCodes.Ldarg_0);
IL.Emit(OpCodes.Call, defaultConstructor);
// __interceptor = (IInterceptor)info.GetValue("__interceptor", typeof(IInterceptor));
IL.Emit(OpCodes.Ldarg_0);
IL.Emit(OpCodes.Ldarg_1);
IL.Emit(OpCodes.Ldstr, "__interceptor");
IL.Emit(OpCodes.Ldloc, interceptorType);
IL.Emit(OpCodes.Callvirt, getValue);
IL.Emit(OpCodes.Castclass, typeof(IInterceptor));
IL.Emit(OpCodes.Stfld, interceptorField);
IL.Emit(OpCodes.Ret);
}
private static void AddSerializationSupport(Type baseType, Type[] baseInterfaces, TypeBuilder typeBuilder, FieldInfo interceptorField, ConstructorBuilder defaultConstructor)
{
ConstructorInfo serializableConstructor = typeof(SerializableAttribute).GetConstructor(new Type[0]);
CustomAttributeBuilder customAttributeBuilder = new CustomAttributeBuilder(serializableConstructor, new object[0]);
typeBuilder.SetCustomAttribute(customAttributeBuilder);
DefineSerializationConstructor(baseInterfaces, typeBuilder, interceptorField, defaultConstructor);
ImplementGetObjectData(baseType, baseInterfaces, typeBuilder, interceptorField);
}
#endif
}
}