@@ -25,8 +25,17 @@ public static class LazyProxyBuilder
25
25
private static readonly ConcurrentDictionary < Type , Lazy < Type > > ProxyTypes =
26
26
new ConcurrentDictionary < Type , Lazy < Type > > ( ) ;
27
27
28
- private static readonly MethodInfo CreateLazyMethod = typeof ( LazyBuilder )
29
- . GetMethod ( "CreateInstance" , BindingFlags . Public | BindingFlags . Static ) ;
28
+ private static readonly MethodInfo CreateLazyMethod = typeof ( LazyProxyImplementation )
29
+ . GetMethod ( nameof ( LazyProxyImplementation . CreateInstance ) , BindingFlags . Public | BindingFlags . Static ) ;
30
+
31
+ private static readonly MethodInfo DisposeLazyMethod = typeof ( LazyProxyImplementation )
32
+ . GetMethod ( nameof ( LazyProxyImplementation . DisposeInstance ) , BindingFlags . Public | BindingFlags . Static ) ;
33
+
34
+ private static readonly Type DisposableInterface = typeof ( IDisposable ) ;
35
+
36
+ private static readonly MethodInfo DisposeMethod = DisposableInterface
37
+ . GetMethod ( nameof ( IDisposable . Dispose ) , BindingFlags . Public | BindingFlags . Instance ) ;
38
+
30
39
31
40
/// <summary>
32
41
/// Defines at runtime a class that implements interface T
@@ -89,7 +98,7 @@ public static object CreateInstance(Type type, Func<object> valueFactory)
89
98
var proxyType = GetType ( type ) ;
90
99
91
100
// Using 'Initialize' method after the instance creation allows to improve performance
92
- // because Activator.CreateInstance executed with arguments is much slower .
101
+ // because Activator.CreateInstance method performance is much worse with arguments .
93
102
var instance = ( LazyProxyBase ) Activator . CreateInstance ( proxyType ) ;
94
103
instance . Initialize ( valueFactory ) ;
95
104
@@ -134,6 +143,7 @@ private static Type DefineProxyType(Type type)
134
143
. AddServiceField ( type , out var serviceField )
135
144
. AddInitializeMethod ( type , serviceField )
136
145
. AddMethods ( type , serviceField )
146
+ . AddDisposeMethodIfNeeded ( type , serviceField )
137
147
. CreateTypeInfo ( ) ;
138
148
}
139
149
@@ -167,8 +177,8 @@ private static TypeBuilder AddServiceField(this TypeBuilder typeBuilder,
167
177
private static TypeBuilder AddInitializeMethod ( this TypeBuilder typeBuilder , Type type , FieldInfo serviceField )
168
178
{
169
179
var methodBuilder = typeBuilder . DefineMethod (
170
- " Initialize" ,
171
- MethodAttributes . Public | MethodAttributes . Virtual ,
180
+ nameof ( LazyProxyBase . Initialize ) ,
181
+ MethodAttributes . Family | MethodAttributes . Virtual ,
172
182
null ,
173
183
new [ ] { typeof ( Func < object > ) }
174
184
) ;
@@ -229,13 +239,42 @@ private static TypeBuilder AddMethods(this TypeBuilder typeBuilder, Type type, F
229
239
return typeBuilder ;
230
240
}
231
241
242
+ private static TypeBuilder AddDisposeMethodIfNeeded ( this TypeBuilder typeBuilder , Type type , FieldInfo serviceField )
243
+ {
244
+ if ( ! DisposableInterface . IsAssignableFrom ( type ) ) {
245
+ return typeBuilder ;
246
+ }
247
+
248
+ var methodBuilder = typeBuilder . DefineMethod (
249
+ DisposeMethod . Name ,
250
+ MethodAttributes . Public | MethodAttributes . Virtual ,
251
+ DisposeMethod . ReturnType ,
252
+ Array . Empty < Type > ( )
253
+ ) ;
254
+
255
+ var disposeLazyMethod = DisposeLazyMethod . MakeGenericMethod ( type ) ;
256
+
257
+ var generator = methodBuilder . GetILGenerator ( ) ;
258
+
259
+ generator . Emit ( OpCodes . Ldarg_0 ) ;
260
+ generator . Emit ( OpCodes . Ldfld , serviceField ) ;
261
+ generator . Emit ( OpCodes . Call , disposeLazyMethod ) ;
262
+ generator . Emit ( OpCodes . Ret ) ;
263
+
264
+ typeBuilder . DefineMethodOverride ( methodBuilder , DisposeMethod ) ;
265
+
266
+ return typeBuilder ;
267
+ }
268
+
232
269
private static IEnumerable < MethodInfo > GetMethods ( Type type )
233
270
{
234
271
const BindingFlags flags = BindingFlags . Public | BindingFlags . Instance ;
235
272
273
+ var isDisposable = DisposableInterface . IsAssignableFrom ( type ) ;
236
274
return type . GetMethods ( flags )
237
275
. Concat ( type . GetInterfaces ( )
238
276
. SelectMany ( @interface => @interface . GetMethods ( flags ) ) )
277
+ . Where ( method => ! isDisposable || method . Name != nameof ( IDisposable . Dispose ) )
239
278
. Distinct ( ) ;
240
279
}
241
280
0 commit comments