Skip to content

Commit f209b1b

Browse files
fixup! Obsolete dynamic proxies
Do additional proxy refactoring * Simplify PeVerify test * Extract default base constructor call in a method
1 parent 08ed505 commit f209b1b

File tree

4 files changed

+36
-35
lines changed

4 files changed

+36
-35
lines changed

src/NHibernate.Test/StaticProxyTest/StaticProxyFactoryFixture.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,14 @@ public void CanCreateProxyForClassWithInternalInterface()
3434
[Test]
3535
public void VerifyFieldInterceptorProxy()
3636
{
37-
var proxyBuilderType = typeof(StaticProxyFactory).Assembly.GetType("NHibernate.Proxy.FieldInterceptorProxyBuilder", true);
38-
var proxyBuilder = proxyBuilderType.GetMethod("CreateProxyType");
39-
Assert.That(proxyBuilder, Is.Not.Null, "Failed to find method CreateProxyType");
37+
var factory = new StaticProxyFactory();
38+
factory.PostInstantiate(typeof(TestClass).FullName, typeof(TestClass), new HashSet<System.Type> {typeof(INHibernateProxy)}, null, null, null);
4039

40+
VerifyGeneratedAssembly(() => factory.GetFieldInterceptionProxy(null));
41+
}
42+
43+
private static void VerifyGeneratedAssembly(System.Action assemblyGenerator)
44+
{
4145
var proxyBuilderHelperType = typeof(StaticProxyFactory).Assembly.GetType("NHibernate.Proxy.ProxyBuilderHelper", true);
4246
var enableSave = proxyBuilderHelperType.GetMethod("EnableDynamicAssemblySaving", BindingFlags.NonPublic | BindingFlags.Static);
4347
Assert.That(enableSave, Is.Not.Null, "Failed to find method EnableDynamicAssemblySaving");
@@ -47,7 +51,7 @@ public void VerifyFieldInterceptorProxy()
4751
enableSave.Invoke(null, new object[] { true, assemblyPath });
4852
try
4953
{
50-
proxyBuilder.Invoke(null, new object[] { typeof(TestClass) });
54+
assemblyGenerator();
5155
}
5256
finally
5357
{

src/NHibernate/Proxy/FieldInterceptorProxyBuilder.cs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ internal static class FieldInterceptorProxyBuilder
1313
private const MethodAttributes constructorAttributes =
1414
MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName;
1515

16-
private static readonly ConstructorInfo ObjectConstructor = typeof(object).GetConstructor(System.Type.EmptyTypes);
17-
1816
private static readonly System.Type FieldInterceptorAccessorType = typeof(IFieldInterceptorAccessor);
1917
private static readonly PropertyInfo AccessorTypeFieldInterceptorProperty =
2018
FieldInterceptorAccessorType.GetProperty(nameof(IFieldInterceptorAccessor.FieldInterceptor));
@@ -114,19 +112,11 @@ private static void ImplementConstructor(TypeBuilder typeBuilder, System.Type pa
114112
{
115113
var constructor = typeBuilder.DefineConstructor(constructorAttributes, CallingConventions.Standard, System.Type.EmptyTypes);
116114

117-
var baseConstructor = parentType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, System.Type.EmptyTypes, null);
118-
119-
// if there is no default constructor, or the default constructor is private/internal, call System.Object constructor
120-
// this works, but the generated assembly will fail PeVerify (cannot use in medium trust for example)
121-
if (baseConstructor == null || baseConstructor.IsPrivate || baseConstructor.IsAssembly)
122-
baseConstructor = ObjectConstructor;
123-
124115
var IL = constructor.GetILGenerator();
125116

126117
constructor.SetImplementationFlags(MethodImplAttributes.IL | MethodImplAttributes.Managed);
127118

128-
IL.Emit(OpCodes.Ldarg_0);
129-
IL.Emit(OpCodes.Call, baseConstructor);
119+
ProxyBuilderHelper.CallDefaultBaseConstructor(IL, parentType);
130120

131121
IL.Emit(OpCodes.Ret);
132122
}

src/NHibernate/Proxy/NHibernateProxyBuilder.cs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ internal class NHibernateProxyBuilder
1515
private const MethodAttributes constructorAttributes =
1616
MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName;
1717

18-
private static readonly ConstructorInfo ObjectConstructor = typeof(object).GetConstructor(System.Type.EmptyTypes);
19-
2018
private static readonly System.Type NHibernateProxyType = typeof(INHibernateProxy);
2119
private static readonly PropertyInfo NHibernateProxyTypeLazyInitializerProperty = NHibernateProxyType.GetProperty(nameof(INHibernateProxy.HibernateLazyInitializer));
2220
private static readonly System.Type LazyInitializerType = typeof(ILazyInitializer);
@@ -139,19 +137,11 @@ private static void ImplementConstructor(TypeBuilder typeBuilder, System.Type pa
139137
{
140138
var constructor = typeBuilder.DefineConstructor(constructorAttributes, CallingConventions.Standard, new[] {LazyInitializerType, typeof(NHibernateProxyFactoryInfo)});
141139

142-
var baseConstructor = parentType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, System.Type.EmptyTypes, null);
143-
144-
// if there is no default constructor, or the default constructor is private/internal, call System.Object constructor
145-
// this works, but the generated assembly will fail PeVerify (cannot use in medium trust for example)
146-
if (baseConstructor == null || baseConstructor.IsPrivate || baseConstructor.IsAssembly)
147-
baseConstructor = ObjectConstructor;
148-
149140
var IL = constructor.GetILGenerator();
150141

151142
constructor.SetImplementationFlags(MethodImplAttributes.IL | MethodImplAttributes.Managed);
152143

153-
IL.Emit(OpCodes.Ldarg_0);
154-
IL.Emit(OpCodes.Call, baseConstructor);
144+
ProxyBuilderHelper.CallDefaultBaseConstructor(IL, parentType);
155145

156146
// __lazyInitializer == lazyInitializer;
157147
IL.Emit(OpCodes.Ldarg_0);

src/NHibernate/Proxy/ProxyBuilderHelper.cs

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ namespace NHibernate.Proxy
1616
{
1717
internal static class ProxyBuilderHelper
1818
{
19+
private static readonly ConstructorInfo ObjectConstructor = typeof(object).GetConstructor(System.Type.EmptyTypes);
20+
1921
#if NETFX
2022
private static bool _saveAssembly;
2123
private static string _saveAssemblyPath;
@@ -64,6 +66,22 @@ internal static void Save(AssemblyBuilder assemblyBuilder)
6466
#endif
6567
}
6668

69+
internal static void CallDefaultBaseConstructor(ILGenerator il, System.Type parentType)
70+
{
71+
var baseConstructor = parentType.GetConstructor(
72+
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public,
73+
null,
74+
System.Type.EmptyTypes,
75+
null);
76+
// if there is no default constructor, or the default constructor is private/internal, call System.Object constructor
77+
// this works, but the generated assembly will fail PeVerify (cannot use in medium trust for example)
78+
if (baseConstructor == null || baseConstructor.IsPrivate || baseConstructor.IsAssembly)
79+
baseConstructor = ObjectConstructor;
80+
81+
il.Emit(OpCodes.Ldarg_0);
82+
il.Emit(OpCodes.Call, baseConstructor);
83+
}
84+
6785
internal static IEnumerable<MethodInfo> GetProxiableMethods(System.Type type, IEnumerable<System.Type> interfaces)
6886
{
6987
const BindingFlags candidateMethodsBindingFlags =
@@ -83,23 +101,23 @@ internal static MethodBuilder GenerateMethodSignature(string name, MethodInfo me
83101
if (method.IsSpecialName)
84102
methodAttributes |= MethodAttributes.SpecialName;
85103

86-
ParameterInfo[] parameters = method.GetParameters();
104+
var parameters = method.GetParameters();
87105

88-
MethodBuilder methodBuilder = typeBuilder.DefineMethod(
106+
var methodBuilder = typeBuilder.DefineMethod(
89107
name,
90108
methodAttributes,
91109
CallingConventions.HasThis,
92110
method.ReturnType,
93111
parameters.Select(param => param.ParameterType).ToArray());
94112

95-
System.Type[] typeArgs = method.GetGenericArguments();
113+
var typeArgs = method.GetGenericArguments();
96114

97115
if (typeArgs.Length > 0)
98116
{
99117
var typeNames = GenerateTypeNames(typeArgs.Length);
100118
var typeArgBuilders = methodBuilder.DefineGenericParameters(typeNames);
101119

102-
for (int index = 0; index < typeArgs.Length; index++)
120+
for (var index = 0; index < typeArgs.Length; index++)
103121
{
104122
// Copy generic parameter attributes (Covariant, Contravariant, ReferenceTypeConstraint,
105123
// NotNullableValueTypeConstraint, DefaultConstructorConstraint).
@@ -150,11 +168,10 @@ private static System.Type BuildTypeConstraint(System.Type typeConstraint, Syste
150168

151169
var args = new System.Type[constraintGenericArguments.Length];
152170
var make = false;
153-
for (int index = 0; index < constraintGenericArguments.Length; index++)
171+
for (var index = 0; index < constraintGenericArguments.Length; index++)
154172
{
155173
var genericArgument = constraintGenericArguments[index];
156-
System.Type result;
157-
if (parametersMap.TryGetValue(genericArgument, out result))
174+
if (parametersMap.TryGetValue(genericArgument, out var result))
158175
{
159176
make = true;
160177
}
@@ -177,9 +194,9 @@ private static System.Type BuildTypeConstraint(System.Type typeConstraint, Syste
177194
private static string[] GenerateTypeNames(int count)
178195
{
179196
var result = new string[count];
180-
for (int index = 0; index < count; index++)
197+
for (var index = 0; index < count; index++)
181198
{
182-
result[index] = string.Format("T{0}", index);
199+
result[index] = $"T{index}";
183200
}
184201

185202
return result;

0 commit comments

Comments
 (0)