Skip to content

Commit 2575b33

Browse files
committed
Generate static proxies
1 parent 4cad8c5 commit 2575b33

9 files changed

+491
-20
lines changed

src/NHibernate/Proxy/AbstractProxyFactory.cs

+29-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Reflection;
4+
using System.Runtime.Serialization;
45
using NHibernate.Engine;
56
using NHibernate.Type;
67
using NHibernate.Util;
@@ -10,7 +11,7 @@ namespace NHibernate.Proxy
1011
/// <summary>
1112
/// Convenient common implementation for ProxyFactory
1213
/// </summary>
13-
public abstract class AbstractProxyFactory: IProxyFactory
14+
public abstract class AbstractProxyFactory: IProxyFactory, ISerializable
1415
{
1516
protected virtual string EntityName { get; private set; }
1617
protected virtual System.Type PersistentClass { get; private set; }
@@ -25,6 +26,21 @@ protected bool IsClassProxy
2526
get { return Interfaces.Length == 1; }
2627
}
2728

29+
protected AbstractProxyFactory()
30+
{
31+
}
32+
33+
protected AbstractProxyFactory(SerializationInfo info, StreamingContext context)
34+
{
35+
EntityName = (string) info.GetValue(nameof(EntityName), typeof(string));
36+
PersistentClass = (System.Type) info.GetValue(nameof(PersistentClass), typeof(System.Type));
37+
Interfaces = (System.Type[]) info.GetValue(nameof(Interfaces), typeof(System.Type[]));
38+
GetIdentifierMethod = (MethodInfo) info.GetValue(nameof(GetIdentifierMethod), typeof(MethodInfo));
39+
SetIdentifierMethod = (MethodInfo) info.GetValue(nameof(SetIdentifierMethod), typeof(MethodInfo));
40+
ComponentIdType = (IAbstractComponentType) info.GetValue(nameof(ComponentIdType), typeof(IAbstractComponentType));
41+
OverridesEquals = (bool) info.GetValue(nameof(OverridesEquals), typeof(bool));
42+
}
43+
2844
public virtual void PostInstantiate(string entityName, System.Type persistentClass, ISet<System.Type> interfaces,
2945
MethodInfo getIdentifierMethod, MethodInfo setIdentifierMethod,
3046
IAbstractComponentType componentIdType)
@@ -51,5 +67,16 @@ public virtual object GetFieldInterceptionProxy(object instanceToWrap)
5167
{
5268
throw new NotSupportedException();
5369
}
70+
71+
public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
72+
{
73+
info.AddValue(nameof(EntityName), EntityName);
74+
info.AddValue(nameof(PersistentClass), PersistentClass);
75+
info.AddValue(nameof(Interfaces), Interfaces);
76+
info.AddValue(nameof(GetIdentifierMethod), GetIdentifierMethod);
77+
info.AddValue(nameof(SetIdentifierMethod), SetIdentifierMethod);
78+
info.AddValue(nameof(ComponentIdType), ComponentIdType);
79+
info.AddValue(nameof(OverridesEquals), OverridesEquals);
80+
}
5481
}
55-
}
82+
}

src/NHibernate/Proxy/DefaultLazyInitializer.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
namespace NHibernate.Proxy
1010
{
11+
//Since v5.1
12+
[Obsolete("This class is not used anymore and will be removed in a future version. Please implement your version of ILazyInitializer")]
1113
[Serializable]
1214
public class DefaultLazyInitializer : BasicLazyInitializer, DynamicProxy.IInterceptor
1315
{
@@ -39,4 +41,4 @@ public object Intercept(InvocationInfo info)
3941
return returnValue;
4042
}
4143
}
42-
}
44+
}
+29-9
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,35 @@
11
using System;
2+
using System.Collections.Concurrent;
3+
using System.Linq.Expressions;
4+
using System.Runtime.Serialization;
25
using NHibernate.Engine;
36
using NHibernate.Intercept;
47
using NHibernate.Proxy.DynamicProxy;
58

69
namespace NHibernate.Proxy
710
{
11+
[Serializable]
812
public class DefaultProxyFactory : AbstractProxyFactory
913
{
10-
private readonly ProxyFactory factory = new ProxyFactory();
14+
static readonly ConcurrentDictionary<ProxyCacheEntry, Func<ILazyInitializer, IProxyFactory, INHibernateProxy>> Cache =
15+
new ConcurrentDictionary<ProxyCacheEntry, Func<ILazyInitializer, IProxyFactory, INHibernateProxy>>();
16+
1117
protected static readonly INHibernateLogger log = NHibernateLogger.For(typeof (DefaultProxyFactory));
1218

19+
public DefaultProxyFactory()
20+
{
21+
}
22+
23+
protected DefaultProxyFactory(SerializationInfo info, StreamingContext context)
24+
: base(info, context) { }
25+
1326
public override INHibernateProxy GetProxy(object id, ISessionImplementor session)
1427
{
1528
try
1629
{
17-
var initializer = new DefaultLazyInitializer(EntityName, PersistentClass, id, GetIdentifierMethod, SetIdentifierMethod, ComponentIdType, session, OverridesEquals);
18-
19-
object proxyInstance = IsClassProxy
20-
? factory.CreateProxy(PersistentClass, initializer, Interfaces)
21-
: factory.CreateProxy(Interfaces[0], initializer, Interfaces);
22-
23-
return (INHibernateProxy) proxyInstance;
30+
var cacheEntry = new ProxyCacheEntry(IsClassProxy ? PersistentClass : typeof(object), Interfaces);
31+
var proxyActivator = Cache.GetOrAdd(cacheEntry, pke => CreateProxyActivator(pke));
32+
return proxyActivator(new LiteLazyInitializer(EntityName, id, session, PersistentClass), this);
2433
}
2534
catch (Exception ex)
2635
{
@@ -29,10 +38,21 @@ public override INHibernateProxy GetProxy(object id, ISessionImplementor session
2938
}
3039
}
3140

41+
Func<ILazyInitializer, IProxyFactory, INHibernateProxy> CreateProxyActivator(ProxyCacheEntry pke)
42+
{
43+
var proxyBuilder = new NHibernateProxyBuilder(GetIdentifierMethod, SetIdentifierMethod, ComponentIdType, OverridesEquals);
44+
var type = proxyBuilder.CreateProxyType(pke.BaseType, pke.Interfaces);
45+
var ctor = type.GetConstructor(new[] {typeof(ILazyInitializer), typeof(IProxyFactory)});
46+
var li = Expression.Parameter(typeof(ILazyInitializer));
47+
var pf = Expression.Parameter(typeof(IProxyFactory));
48+
return Expression.Lambda<Func<ILazyInitializer, IProxyFactory, INHibernateProxy>>(Expression.New(ctor, li, pf), li, pf).Compile();
49+
}
50+
3251
public override object GetFieldInterceptionProxy(object instanceToWrap)
3352
{
53+
var factory = new ProxyFactory();
3454
var interceptor = new DefaultDynamicLazyFieldInterceptor();
3555
return factory.CreateProxy(PersistentClass, interceptor, new[] { typeof(IFieldInterceptorAccessor) });
3656
}
3757
}
38-
}
58+
}

src/NHibernate/Proxy/DynamicProxy/DefaultProxyMethodBuilder.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public DefaultyProxyMethodBuilder(IMethodBodyEmitter emitter)
3030

3131
public IMethodBodyEmitter MethodBodyEmitter { get; private set; }
3232

33-
private static MethodBuilder GenerateMethodSignature(string name, MethodInfo method, TypeBuilder typeBuilder)
33+
internal static MethodBuilder GenerateMethodSignature(string name, MethodInfo method, TypeBuilder typeBuilder)
3434
{
3535
//TODO: Should we use attributes of base method?
3636
var methodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual;

src/NHibernate/Proxy/DynamicProxy/ProxyFactory.cs

+7-7
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ public sealed class ProxyFactory
2121
{
2222
internal static readonly ConcurrentDictionary<ProxyCacheEntry, TypeInfo> _cache = new ConcurrentDictionary<ProxyCacheEntry, TypeInfo>();
2323

24-
private static readonly ConstructorInfo defaultBaseConstructor = typeof(object).GetConstructor(new System.Type[0]);
24+
internal static readonly ConstructorInfo defaultBaseConstructor = typeof(object).GetConstructor(new System.Type[0]);
2525

2626
private static readonly MethodInfo getValue = ReflectHelper.GetMethod<SerializationInfo>(
2727
si => si.GetValue(null, null));
28-
private static readonly MethodInfo setType = ReflectHelper.GetMethod<SerializationInfo>(
28+
internal static readonly MethodInfo setType = ReflectHelper.GetMethod<SerializationInfo>(
2929
si => si.SetType(null));
3030
private static readonly MethodInfo addValue = ReflectHelper.GetMethod<SerializationInfo>(
3131
si => si.AddValue(null, null));
@@ -129,7 +129,7 @@ private TypeInfo CreateUncachedProxyType(System.Type baseType, IReadOnlyCollecti
129129
return proxyType;
130130
}
131131

132-
private IEnumerable<MethodInfo> GetProxiableMethods(System.Type type, IEnumerable<System.Type> interfaces)
132+
internal static IEnumerable<MethodInfo> GetProxiableMethods(System.Type type, IEnumerable<System.Type> interfaces)
133133
{
134134
const BindingFlags candidateMethodsBindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
135135
return
@@ -139,7 +139,7 @@ private IEnumerable<MethodInfo> GetProxiableMethods(System.Type type, IEnumerabl
139139
.Distinct();
140140
}
141141

142-
private static ConstructorBuilder DefineConstructor(TypeBuilder typeBuilder, System.Type parentType)
142+
internal static ConstructorBuilder DefineConstructor(TypeBuilder typeBuilder, System.Type parentType)
143143
{
144144
const MethodAttributes constructorAttributes = MethodAttributes.Public |
145145
MethodAttributes.HideBySig | MethodAttributes.SpecialName |
@@ -166,7 +166,7 @@ private static ConstructorBuilder DefineConstructor(TypeBuilder typeBuilder, Sys
166166
return constructor;
167167
}
168168

169-
private static void ImplementGetObjectData(System.Type baseType, IReadOnlyCollection<System.Type> baseInterfaces, TypeBuilder typeBuilder, FieldInfo interceptorField)
169+
internal static void ImplementGetObjectData(System.Type baseType, IReadOnlyCollection<System.Type> baseInterfaces, TypeBuilder typeBuilder, FieldInfo interceptorField)
170170
{
171171
const MethodAttributes attributes = MethodAttributes.Public | MethodAttributes.HideBySig |
172172
MethodAttributes.Virtual;
@@ -217,7 +217,7 @@ private static void ImplementGetObjectData(System.Type baseType, IReadOnlyCollec
217217
IL.Emit(OpCodes.Ret);
218218
}
219219

220-
private static void DefineSerializationConstructor(TypeBuilder typeBuilder, FieldInfo interceptorField, ConstructorBuilder defaultConstructor)
220+
internal static void DefineSerializationConstructor(TypeBuilder typeBuilder, FieldInfo interceptorField, ConstructorBuilder defaultConstructor)
221221
{
222222
const MethodAttributes constructorAttributes = MethodAttributes.Public |
223223
MethodAttributes.HideBySig | MethodAttributes.SpecialName |
@@ -254,7 +254,7 @@ private static void DefineSerializationConstructor(TypeBuilder typeBuilder, Fiel
254254
IL.Emit(OpCodes.Ret);
255255
}
256256

257-
private static void AddSerializationSupport(System.Type baseType, IReadOnlyCollection<System.Type> baseInterfaces, TypeBuilder typeBuilder, FieldInfo interceptorField, ConstructorBuilder defaultConstructor)
257+
internal static void AddSerializationSupport(System.Type baseType, IReadOnlyCollection<System.Type> baseInterfaces, TypeBuilder typeBuilder, FieldInfo interceptorField, ConstructorBuilder defaultConstructor)
258258
{
259259
ConstructorInfo serializableConstructor = typeof(SerializableAttribute).GetConstructor(new System.Type[0]);
260260
var customAttributeBuilder = new CustomAttributeBuilder(serializableConstructor, new object[0]);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System;
2+
using NHibernate.Engine;
3+
4+
namespace NHibernate.Proxy
5+
{
6+
[Serializable]
7+
class LiteLazyInitializer : AbstractLazyInitializer
8+
{
9+
internal LiteLazyInitializer(string entityName, object id, ISessionImplementor session, System.Type persistentClass)
10+
: base(entityName, id, session)
11+
{
12+
PersistentClass = persistentClass;
13+
}
14+
15+
public override System.Type PersistentClass { get; }
16+
}
17+
}

0 commit comments

Comments
 (0)