@@ -27,21 +27,32 @@ public static class LazyProxyBuilder
2727
2828 /// <summary>
2929 /// Defines at runtime a class that implements interface T
30- /// and proxis all invocations to <see cref="Lazy{T}"/> of this interface.
30+ /// and proxies all invocations to <see cref="Lazy{T}"/> of this interface.
3131 /// </summary>
3232 /// <typeparam name="T">The interface proxy type implements.</typeparam>
3333 /// <returns>The lazy proxy type.</returns>
3434 public static Type BuildLazyProxyType < T > ( )
35+ {
36+ return BuildLazyProxyType ( typeof ( T ) ) ;
37+ }
38+
39+ /// <summary>
40+ /// Defines at runtime a class that implements interface of Type
41+ /// and proxies all invocations to <see cref="Lazy{T}"/> of this interface.
42+ /// </summary>
43+ /// <param name="type">The interface proxy type implements.</param>
44+ /// <returns>The lazy proxy type.</returns>
45+ public static Type BuildLazyProxyType ( Type type )
3546 {
3647 // There is no way to constraint it on the compilation step.
37- if ( ! typeof ( T ) . IsInterface )
48+ if ( ! type . IsInterface )
3849 {
3950 throw new NotSupportedException ( "The lazy proxy is supported only for interfaces." ) ;
4051 }
4152
4253 // Lazy is used to guarantee the valueFactory is invoked only once.
4354 // More info: http://reedcopsey.com/2011/01/16/concurrentdictionarytkeytvalue-used-with-lazyt/
44- var lazy = ProxyTypes . GetOrAdd ( typeof ( T ) , type => new Lazy < Type > ( DefineProxyType < T > ) ) ;
55+ var lazy = ProxyTypes . GetOrAdd ( type , t => new Lazy < Type > ( ( ) => DefineProxyType ( t ) ) ) ;
4556 return lazy . Value ;
4657 }
4758
@@ -82,41 +93,45 @@ public static T CreateLazyProxyInstance<T>(Func<T> valueFactory)
8293 /// </summary>
8394 /// <typeparam name="T">The interface proxy type implements.</typeparam>
8495 /// <returns>The lazy proxy type.</returns>
85- private static Type DefineProxyType < T > ( )
96+ private static Type DefineProxyType ( Type type )
8697 {
8798 // Add a guid to avoid problems with defining generic types with different type parameters.
8899 // Dashes are allowed by IL but they are removed to match the class names in C#.
89100 var guid = Guid . NewGuid ( ) . ToString ( ) . Replace ( "-" , "" ) ;
90101
91- var type = typeof ( T ) ;
92102 var typeName = $ "{ type . Namespace } .{ LazyProxyTypeSuffix } _{ guid } _{ type . Name } ";
93103
94104 return ModuleBuilder . DefineType ( typeName , TypeAttributes . Public )
95- . AddInterfaceImplementation < T > ( )
96- . AddServiceField < T > ( out var serviceField )
97- . AddConstructor < T > ( serviceField )
98- . AddMethods < T > ( serviceField )
105+ . AddInterface ( type )
106+ . AddServiceField ( type , out var serviceField )
107+ . AddConstructor ( type , serviceField )
108+ . AddMethods ( type , serviceField )
99109 . CreateTypeInfo ( ) ;
100110 }
101111
102- private static TypeBuilder AddInterfaceImplementation < T > ( this TypeBuilder typeBuilder )
112+ private static TypeBuilder AddInterface ( this TypeBuilder typeBuilder , Type type )
103113 {
104- typeBuilder . AddInterfaceImplementation ( typeof ( T ) ) ;
114+ typeBuilder . AddInterfaceImplementation ( type ) ;
105115 return typeBuilder ;
106116 }
107117
108- private static TypeBuilder AddServiceField < T > ( this TypeBuilder typeBuilder , out FieldInfo serviceField )
118+ private static TypeBuilder AddServiceField ( this TypeBuilder typeBuilder ,
119+ Type type , out FieldInfo serviceField )
109120 {
110- serviceField = typeBuilder . DefineField ( ServiceFieldName , typeof ( Lazy < T > ) , FieldAttributes . Private ) ;
121+ serviceField = typeBuilder . DefineField (
122+ ServiceFieldName ,
123+ typeof ( Lazy < > ) . MakeGenericType ( type ) ,
124+ FieldAttributes . Private ) ;
125+
111126 return typeBuilder ;
112127 }
113128
114- private static TypeBuilder AddConstructor < T > ( this TypeBuilder typeBuilder , FieldInfo serviceField )
129+ private static TypeBuilder AddConstructor ( this TypeBuilder typeBuilder , Type type , FieldInfo serviceField )
115130 {
116131 var constructorBuilder = typeBuilder . DefineConstructor (
117132 MethodAttributes . Public ,
118133 CallingConventions . Standard ,
119- new [ ] { typeof ( Lazy < T > ) }
134+ new [ ] { typeof ( Lazy < > ) . MakeGenericType ( type ) }
120135 ) ;
121136
122137 var generator = constructorBuilder . GetILGenerator ( ) ;
@@ -129,10 +144,10 @@ private static TypeBuilder AddConstructor<T>(this TypeBuilder typeBuilder, Field
129144 return typeBuilder ;
130145 }
131146
132- private static TypeBuilder AddMethods < T > ( this TypeBuilder typeBuilder , FieldInfo serviceField )
147+ private static TypeBuilder AddMethods ( this TypeBuilder typeBuilder , Type type , FieldInfo serviceField )
133148 {
134- var methods = GetMethods < T > ( ) ;
135- var getServiceValueMethod = GetGetServiceValueMethod < T > ( serviceField ) ;
149+ var methods = GetMethods ( type ) ;
150+ var getServiceValueMethod = GetGetServiceValueMethod ( serviceField ) ;
136151
137152 foreach ( var method in methods )
138153 {
@@ -176,20 +191,20 @@ private static TypeBuilder AddMethods<T>(this TypeBuilder typeBuilder, FieldInfo
176191 return typeBuilder ;
177192 }
178193
179- private static IEnumerable < MethodInfo > GetMethods < T > ( )
194+ private static IEnumerable < MethodInfo > GetMethods ( Type type )
180195 {
181196 const BindingFlags flags = BindingFlags . Public | BindingFlags . Instance ;
182197
183- return typeof ( T ) . GetMethods ( flags )
184- . Concat ( typeof ( T ) . GetInterfaces ( )
198+ return type . GetMethods ( flags )
199+ . Concat ( type . GetInterfaces ( )
185200 . SelectMany ( @interface => @interface . GetMethods ( flags ) ) )
186201 . Distinct ( ) ;
187202 }
188203
189- private static MethodInfo GetGetServiceValueMethod < T > ( FieldInfo serviceField )
204+ private static MethodInfo GetGetServiceValueMethod ( FieldInfo serviceField )
190205 {
191206 // ReSharper disable once PossibleNullReferenceException
192- return serviceField . FieldType . GetProperty ( nameof ( Lazy < T > . Value ) ) . GetGetMethod ( true ) ;
207+ return serviceField . FieldType . GetProperty ( " Value" ) . GetGetMethod ( true ) ;
193208 }
194209 }
195210}
0 commit comments