7
7
#endregion
8
8
9
9
using System ;
10
+ using System . Collections . Concurrent ;
10
11
using System . Collections . Generic ;
11
12
using System . Linq ;
12
13
using System . Reflection ;
@@ -19,6 +20,8 @@ namespace NHibernate.Proxy.DynamicProxy
19
20
{
20
21
public sealed class ProxyFactory
21
22
{
23
+ internal static readonly ConcurrentDictionary < ProxyCacheEntry , Lazy < TypeInfo > > _cache = new ConcurrentDictionary < ProxyCacheEntry , Lazy < TypeInfo > > ( ) ;
24
+
22
25
private static readonly ConstructorInfo defaultBaseConstructor = typeof ( object ) . GetConstructor ( new System . Type [ 0 ] ) ;
23
26
24
27
private static readonly MethodInfo getValue = ReflectHelper . GetMethod < SerializationInfo > (
@@ -39,58 +42,40 @@ public ProxyFactory(IProxyMethodBuilder proxyMethodBuilder)
39
42
40
43
public ProxyFactory ( IProxyMethodBuilder proxyMethodBuilder , IProxyAssemblyBuilder proxyAssemblyBuilder )
41
44
{
42
- if ( proxyMethodBuilder == null )
43
- {
44
- throw new ArgumentNullException ( "proxyMethodBuilder" ) ;
45
- }
46
- ProxyMethodBuilder = proxyMethodBuilder ;
45
+ ProxyMethodBuilder = proxyMethodBuilder ?? throw new ArgumentNullException ( nameof ( proxyMethodBuilder ) ) ;
47
46
ProxyAssemblyBuilder = proxyAssemblyBuilder ;
48
47
Cache = new ProxyCache ( ) ;
49
48
}
50
49
51
- public IProxyCache Cache { get ; private set ; }
50
+ public IProxyCache Cache { get ; }
52
51
53
- public IProxyMethodBuilder ProxyMethodBuilder { get ; private set ; }
52
+ public IProxyMethodBuilder ProxyMethodBuilder { get ; }
54
53
55
- public IProxyAssemblyBuilder ProxyAssemblyBuilder { get ; private set ; }
54
+ public IProxyAssemblyBuilder ProxyAssemblyBuilder { get ; }
56
55
57
56
public object CreateProxy ( System . Type instanceType , IInterceptor interceptor , params System . Type [ ] baseInterfaces )
58
57
{
59
58
System . Type proxyType = CreateProxyType ( instanceType , baseInterfaces ) ;
60
59
object result = Activator . CreateInstance ( proxyType ) ;
61
60
var proxy = ( IProxy ) result ;
62
61
proxy . Interceptor = interceptor ;
63
-
64
62
return result ;
65
63
}
66
64
67
65
public System . Type CreateProxyType ( System . Type baseType , params System . Type [ ] interfaces )
68
66
{
69
- System . Type [ ] baseInterfaces = ReferenceEquals ( null , interfaces ) ? new System . Type [ 0 ] : interfaces . Where ( t => t != null ) . ToArray ( ) ;
70
-
71
- TypeInfo proxyTypeInfo ;
72
-
73
- // Reuse the previous results, if possible, Fast path without locking.
74
- if ( Cache . TryGetProxyType ( baseType , baseInterfaces , out proxyTypeInfo ) )
75
- return proxyTypeInfo ;
67
+ if ( baseType == null ) throw new ArgumentNullException ( nameof ( baseType ) ) ;
76
68
77
- lock ( Cache )
78
- {
79
- // Recheck in case we got interrupted.
80
- if ( ! Cache . TryGetProxyType ( baseType , baseInterfaces , out proxyTypeInfo ) )
81
- {
82
- proxyTypeInfo = CreateUncachedProxyType ( baseType , baseInterfaces ) ;
69
+ var baseInterfaces = ReferenceEquals ( null , interfaces ) ? System . Type . EmptyTypes : interfaces . Where ( t => t != null ) . ToArray ( ) ;
83
70
84
- // Cache the proxy type
85
- if ( proxyTypeInfo != null && Cache != null )
86
- Cache . StoreProxyType ( proxyTypeInfo , baseType , baseInterfaces ) ;
87
- }
71
+ var typeFactory = _cache . GetOrAdd (
72
+ new ProxyCacheEntry ( baseType , baseInterfaces ) ,
73
+ k => new Lazy < TypeInfo > ( ( ) => CreateUncachedProxyType ( k . BaseType , k . Interfaces ) ) ) ;
88
74
89
- return proxyTypeInfo ;
90
- }
75
+ return typeFactory . Value ;
91
76
}
92
77
93
- private TypeInfo CreateUncachedProxyType ( System . Type baseType , System . Type [ ] baseInterfaces )
78
+ private TypeInfo CreateUncachedProxyType ( System . Type baseType , IReadOnlyCollection < System . Type > baseInterfaces )
94
79
{
95
80
AppDomain currentDomain = AppDomain . CurrentDomain ;
96
81
string typeName = string . Format ( "{0}Proxy" , baseType . Name ) ;
@@ -104,8 +89,7 @@ private TypeInfo CreateUncachedProxyType(System.Type baseType, System.Type[] bas
104
89
TypeAttributes typeAttributes = TypeAttributes . AutoClass | TypeAttributes . Class |
105
90
TypeAttributes . Public | TypeAttributes . BeforeFieldInit ;
106
91
107
- var interfaces = new HashSet < System . Type > ( ) ;
108
- interfaces . Merge ( baseInterfaces ) ;
92
+ var interfaces = new HashSet < System . Type > ( baseInterfaces ) ;
109
93
110
94
// Use the proxy dummy as the base type
111
95
// since we're not inheriting from any class type
@@ -117,11 +101,8 @@ private TypeInfo CreateUncachedProxyType(System.Type baseType, System.Type[] bas
117
101
}
118
102
119
103
// Add any inherited interfaces
120
- System . Type [ ] computedInterfaces = interfaces . ToArray ( ) ;
121
- foreach ( System . Type interfaceType in computedInterfaces )
122
- {
123
- interfaces . Merge ( GetInterfaces ( interfaceType ) ) ;
124
- }
104
+ var list = interfaces . SelectMany ( GetAllInterfaces ) . ToArray ( ) ;
105
+ interfaces . UnionWith ( list ) ;
125
106
126
107
// Add the ISerializable interface so that it can be implemented
127
108
interfaces . Add ( typeof ( ISerializable ) ) ;
@@ -151,19 +132,13 @@ private TypeInfo CreateUncachedProxyType(System.Type baseType, System.Type[] bas
151
132
return proxyType ;
152
133
}
153
134
154
- private IEnumerable < System . Type > GetInterfaces ( System . Type currentType )
135
+ private static IEnumerable < System . Type > GetAllInterfaces ( System . Type currentType )
155
136
{
156
- return GetAllInterfaces ( currentType ) ;
157
- }
158
-
159
- private IEnumerable < System . Type > GetAllInterfaces ( System . Type currentType )
160
- {
161
- System . Type [ ] interfaces = currentType . GetInterfaces ( ) ;
162
-
163
- foreach ( System . Type current in interfaces )
137
+ var interfaces = currentType . GetInterfaces ( ) ;
138
+ foreach ( var current in interfaces )
164
139
{
165
140
yield return current ;
166
- foreach ( System . Type @interface in GetAllInterfaces ( current ) )
141
+ foreach ( var @interface in GetAllInterfaces ( current ) )
167
142
{
168
143
yield return @interface ;
169
144
}
@@ -173,10 +148,11 @@ private TypeInfo CreateUncachedProxyType(System.Type baseType, System.Type[] bas
173
148
private IEnumerable < MethodInfo > GetProxiableMethods ( System . Type type , IEnumerable < System . Type > interfaces )
174
149
{
175
150
const BindingFlags candidateMethodsBindingFlags = BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Instance ;
176
- return
151
+ return
177
152
type . GetMethods ( candidateMethodsBindingFlags )
178
- . Where ( method=> method . IsProxiable ( ) )
179
- . Concat ( interfaces . SelectMany ( interfaceType => interfaceType . GetMethods ( ) ) ) . Distinct ( ) ;
153
+ . Where ( method => method . IsProxiable ( ) )
154
+ . Concat ( interfaces . SelectMany ( interfaceType => interfaceType . GetMethods ( ) ) )
155
+ . Distinct ( ) ;
180
156
}
181
157
182
158
private static ConstructorBuilder DefineConstructor ( TypeBuilder typeBuilder , System . Type parentType )
@@ -206,7 +182,7 @@ private static ConstructorBuilder DefineConstructor(TypeBuilder typeBuilder, Sys
206
182
return constructor ;
207
183
}
208
184
209
- private static void ImplementGetObjectData ( System . Type baseType , System . Type [ ] baseInterfaces , TypeBuilder typeBuilder , FieldInfo interceptorField )
185
+ private static void ImplementGetObjectData ( System . Type baseType , IReadOnlyCollection < System . Type > baseInterfaces , TypeBuilder typeBuilder , FieldInfo interceptorField )
210
186
{
211
187
const MethodAttributes attributes = MethodAttributes . Public | MethodAttributes . HideBySig |
212
188
MethodAttributes . Virtual ;
@@ -236,7 +212,7 @@ private static void ImplementGetObjectData(System.Type baseType, System.Type[] b
236
212
IL . Emit ( OpCodes . Ldstr , baseType . AssemblyQualifiedName ) ;
237
213
IL . Emit ( OpCodes . Callvirt , addValue ) ;
238
214
239
- int baseInterfaceCount = baseInterfaces . Length ;
215
+ int baseInterfaceCount = baseInterfaces . Count ;
240
216
241
217
// Save the number of base interfaces
242
218
IL . Emit ( OpCodes . Ldarg_1 ) ;
@@ -249,7 +225,7 @@ private static void ImplementGetObjectData(System.Type baseType, System.Type[] b
249
225
foreach ( System . Type baseInterface in baseInterfaces )
250
226
{
251
227
IL . Emit ( OpCodes . Ldarg_1 ) ;
252
- IL . Emit ( OpCodes . Ldstr , string . Format ( "__baseInterface{0}" , index ++ ) ) ;
228
+ IL . Emit ( OpCodes . Ldstr , String . Format ( "__baseInterface{0}" , index ++ ) ) ;
253
229
IL . Emit ( OpCodes . Ldstr , baseInterface . AssemblyQualifiedName ) ;
254
230
IL . Emit ( OpCodes . Callvirt , addValue ) ;
255
231
}
@@ -294,7 +270,7 @@ private static void DefineSerializationConstructor(TypeBuilder typeBuilder, Fiel
294
270
IL . Emit ( OpCodes . Ret ) ;
295
271
}
296
272
297
- private static void AddSerializationSupport ( System . Type baseType , System . Type [ ] baseInterfaces , TypeBuilder typeBuilder , FieldInfo interceptorField , ConstructorBuilder defaultConstructor )
273
+ private static void AddSerializationSupport ( System . Type baseType , IReadOnlyCollection < System . Type > baseInterfaces , TypeBuilder typeBuilder , FieldInfo interceptorField , ConstructorBuilder defaultConstructor )
298
274
{
299
275
ConstructorInfo serializableConstructor = typeof ( SerializableAttribute ) . GetConstructor ( new System . Type [ 0 ] ) ;
300
276
var customAttributeBuilder = new CustomAttributeBuilder ( serializableConstructor , new object [ 0 ] ) ;
@@ -304,4 +280,4 @@ private static void AddSerializationSupport(System.Type baseType, System.Type[]
304
280
ImplementGetObjectData ( baseType , baseInterfaces , typeBuilder , interceptorField ) ;
305
281
}
306
282
}
307
- }
283
+ }
0 commit comments