77#endregion
88
99using System ;
10+ using System . Collections . Concurrent ;
1011using System . Collections . Generic ;
1112using System . Linq ;
1213using System . Reflection ;
@@ -19,6 +20,8 @@ namespace NHibernate.Proxy.DynamicProxy
1920{
2021 public sealed class ProxyFactory
2122 {
23+ internal static readonly ConcurrentDictionary < ProxyCacheEntry , Lazy < TypeInfo > > _cache = new ConcurrentDictionary < ProxyCacheEntry , Lazy < TypeInfo > > ( ) ;
24+
2225 private static readonly ConstructorInfo defaultBaseConstructor = typeof ( object ) . GetConstructor ( new System . Type [ 0 ] ) ;
2326
2427 private static readonly MethodInfo getValue = ReflectHelper . GetMethod < SerializationInfo > (
@@ -39,58 +42,40 @@ public ProxyFactory(IProxyMethodBuilder proxyMethodBuilder)
3942
4043 public ProxyFactory ( IProxyMethodBuilder proxyMethodBuilder , IProxyAssemblyBuilder proxyAssemblyBuilder )
4144 {
42- if ( proxyMethodBuilder == null )
43- {
44- throw new ArgumentNullException ( "proxyMethodBuilder" ) ;
45- }
46- ProxyMethodBuilder = proxyMethodBuilder ;
45+ ProxyMethodBuilder = proxyMethodBuilder ?? throw new ArgumentNullException ( nameof ( proxyMethodBuilder ) ) ;
4746 ProxyAssemblyBuilder = proxyAssemblyBuilder ;
4847 Cache = new ProxyCache ( ) ;
4948 }
5049
51- public IProxyCache Cache { get ; private set ; }
50+ public IProxyCache Cache { get ; }
5251
53- public IProxyMethodBuilder ProxyMethodBuilder { get ; private set ; }
52+ public IProxyMethodBuilder ProxyMethodBuilder { get ; }
5453
55- public IProxyAssemblyBuilder ProxyAssemblyBuilder { get ; private set ; }
54+ public IProxyAssemblyBuilder ProxyAssemblyBuilder { get ; }
5655
5756 public object CreateProxy ( System . Type instanceType , IInterceptor interceptor , params System . Type [ ] baseInterfaces )
5857 {
5958 System . Type proxyType = CreateProxyType ( instanceType , baseInterfaces ) ;
6059 object result = Activator . CreateInstance ( proxyType ) ;
6160 var proxy = ( IProxy ) result ;
6261 proxy . Interceptor = interceptor ;
63-
6462 return result ;
6563 }
6664
6765 public System . Type CreateProxyType ( System . Type baseType , params System . Type [ ] interfaces )
6866 {
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 ) ) ;
7668
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 ( ) ;
8370
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 ) ) ) ;
8874
89- return proxyTypeInfo ;
90- }
75+ return typeFactory . Value ;
9176 }
9277
93- private TypeInfo CreateUncachedProxyType ( System . Type baseType , System . Type [ ] baseInterfaces )
78+ private TypeInfo CreateUncachedProxyType ( System . Type baseType , IReadOnlyCollection < System . Type > baseInterfaces )
9479 {
9580 AppDomain currentDomain = AppDomain . CurrentDomain ;
9681 string typeName = string . Format ( "{0}Proxy" , baseType . Name ) ;
@@ -104,8 +89,7 @@ private TypeInfo CreateUncachedProxyType(System.Type baseType, System.Type[] bas
10489 TypeAttributes typeAttributes = TypeAttributes . AutoClass | TypeAttributes . Class |
10590 TypeAttributes . Public | TypeAttributes . BeforeFieldInit ;
10691
107- var interfaces = new HashSet < System . Type > ( ) ;
108- interfaces . Merge ( baseInterfaces ) ;
92+ var interfaces = new HashSet < System . Type > ( baseInterfaces ) ;
10993
11094 // Use the proxy dummy as the base type
11195 // since we're not inheriting from any class type
@@ -117,11 +101,8 @@ private TypeInfo CreateUncachedProxyType(System.Type baseType, System.Type[] bas
117101 }
118102
119103 // 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 ) ;
125106
126107 // Add the ISerializable interface so that it can be implemented
127108 interfaces . Add ( typeof ( ISerializable ) ) ;
@@ -151,19 +132,13 @@ private TypeInfo CreateUncachedProxyType(System.Type baseType, System.Type[] bas
151132 return proxyType ;
152133 }
153134
154- private IEnumerable < System . Type > GetInterfaces ( System . Type currentType )
135+ private static IEnumerable < System . Type > GetAllInterfaces ( System . Type currentType )
155136 {
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 )
164139 {
165140 yield return current ;
166- foreach ( System . Type @interface in GetAllInterfaces ( current ) )
141+ foreach ( var @interface in GetAllInterfaces ( current ) )
167142 {
168143 yield return @interface ;
169144 }
@@ -173,10 +148,11 @@ private TypeInfo CreateUncachedProxyType(System.Type baseType, System.Type[] bas
173148 private IEnumerable < MethodInfo > GetProxiableMethods ( System . Type type , IEnumerable < System . Type > interfaces )
174149 {
175150 const BindingFlags candidateMethodsBindingFlags = BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Instance ;
176- return
151+ return
177152 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 ( ) ;
180156 }
181157
182158 private static ConstructorBuilder DefineConstructor ( TypeBuilder typeBuilder , System . Type parentType )
@@ -206,7 +182,7 @@ private static ConstructorBuilder DefineConstructor(TypeBuilder typeBuilder, Sys
206182 return constructor ;
207183 }
208184
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 )
210186 {
211187 const MethodAttributes attributes = MethodAttributes . Public | MethodAttributes . HideBySig |
212188 MethodAttributes . Virtual ;
@@ -236,7 +212,7 @@ private static void ImplementGetObjectData(System.Type baseType, System.Type[] b
236212 IL . Emit ( OpCodes . Ldstr , baseType . AssemblyQualifiedName ) ;
237213 IL . Emit ( OpCodes . Callvirt , addValue ) ;
238214
239- int baseInterfaceCount = baseInterfaces . Length ;
215+ int baseInterfaceCount = baseInterfaces . Count ;
240216
241217 // Save the number of base interfaces
242218 IL . Emit ( OpCodes . Ldarg_1 ) ;
@@ -249,7 +225,7 @@ private static void ImplementGetObjectData(System.Type baseType, System.Type[] b
249225 foreach ( System . Type baseInterface in baseInterfaces )
250226 {
251227 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 ++ ) ) ;
253229 IL . Emit ( OpCodes . Ldstr , baseInterface . AssemblyQualifiedName ) ;
254230 IL . Emit ( OpCodes . Callvirt , addValue ) ;
255231 }
@@ -294,7 +270,7 @@ private static void DefineSerializationConstructor(TypeBuilder typeBuilder, Fiel
294270 IL . Emit ( OpCodes . Ret ) ;
295271 }
296272
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 )
298274 {
299275 ConstructorInfo serializableConstructor = typeof ( SerializableAttribute ) . GetConstructor ( new System . Type [ 0 ] ) ;
300276 var customAttributeBuilder = new CustomAttributeBuilder ( serializableConstructor , new object [ 0 ] ) ;
@@ -304,4 +280,4 @@ private static void AddSerializationSupport(System.Type baseType, System.Type[]
304280 ImplementGetObjectData ( baseType , baseInterfaces , typeBuilder , interceptorField ) ;
305281 }
306282 }
307- }
283+ }
0 commit comments