Skip to content

Remove copy-paste remnants from FieldInterceptorProxyBuilder #1816

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 36 additions & 37 deletions src/NHibernate/Proxy/FieldInterceptorProxyBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.Serialization;
Expand Down Expand Up @@ -37,6 +35,13 @@ internal static class FieldInterceptorProxyBuilder

public static TypeInfo CreateProxyType(System.Type baseType)
{
if (baseType.IsInterface)
{
throw new ArgumentException(
$"Field interceptor proxy does not support being build on an interface baseType ({baseType.FullName}).",
nameof(baseType));
}

// Avoid having a suffix ending with "Proxy", for disambiguation with INHibernateProxy proxies
var typeName = $"{baseType.Name}ProxyForFieldInterceptor";
var assemblyName = $"{typeName}Assembly";
Expand All @@ -49,40 +54,25 @@ public static TypeInfo CreateProxyType(System.Type baseType)

const TypeAttributes typeAttributes = TypeAttributes.AutoClass | TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.BeforeFieldInit;

var interfaces = new HashSet<System.Type>
var interfaces = new[]
{
typeof(IFieldInterceptorAccessor),
typeof(ISerializable)
};

// Use the object as the base type
// since we're not inheriting from any class type
var parentType = baseType;
if (baseType.IsInterface)
{
throw new ArgumentException(
$"Field interceptor proxy does not support being build on an interface baseType ({baseType.FullName}).",
nameof(baseType));
}

interfaces.RemoveWhere(i => !i.IsVisible);

var typeBuilder = moduleBuilder.DefineType(typeName, typeAttributes, parentType, interfaces.ToArray());
var typeBuilder = moduleBuilder.DefineType(typeName, typeAttributes, baseType, interfaces);

var fieldInterceptorField = typeBuilder.DefineField("__fieldInterceptor", FieldInterceptorType, FieldAttributes.Private);
var proxyInfoField = typeBuilder.DefineField("__proxyInfo", typeof(NHibernateProxyFactoryInfo), FieldAttributes.Private);

ImplementConstructor(typeBuilder, parentType, proxyInfoField);

// Provide a custom implementation of ISerializable instead of redirecting it back to the interceptor
foreach (var method in ProxyBuilderHelper.GetProxiableMethods(baseType, interfaces.Except(new[] { typeof(ISerializable) })))
ImplementConstructor(typeBuilder, baseType, proxyInfoField);

foreach (var method in ProxyBuilderHelper.GetProxiableMethods(baseType))
{
CreateProxiedMethod(typeBuilder, method, fieldInterceptorField);
}

ProxyBuilderHelper.MakeProxySerializable(typeBuilder);
ImplementDeserializationConstructor(typeBuilder, parentType);
ImplementGetObjectData(typeBuilder, proxyInfoField, fieldInterceptorField, parentType);
ImplementIFieldInterceptorAccessor(typeBuilder, fieldInterceptorField);
ImplementISerializable(typeBuilder, proxyInfoField, fieldInterceptorField, baseType);

var proxyType = typeBuilder.CreateTypeInfo();

Expand All @@ -93,15 +83,7 @@ public static TypeInfo CreateProxyType(System.Type baseType)

private static void CreateProxiedMethod(TypeBuilder typeBuilder, MethodInfo method, FieldInfo fieldInterceptorField)
{
if (method == AccessorTypeFieldInterceptorProperty.GetMethod)
{
ImplementGetFieldInterceptor(typeBuilder, method, fieldInterceptorField);
}
else if (method == AccessorTypeFieldInterceptorProperty.SetMethod)
{
ImplementSetFieldInterceptor(typeBuilder, method, fieldInterceptorField);
}
else if (ReflectHelper.IsPropertyGet(method))
if (ReflectHelper.IsPropertyGet(method))
{
ImplementGet(typeBuilder, method, fieldInterceptorField);
}
Expand Down Expand Up @@ -133,6 +115,17 @@ private static void ImplementConstructor(TypeBuilder typeBuilder, System.Type pa
IL.Emit(OpCodes.Ret);
}

private static void ImplementISerializable(
TypeBuilder typeBuilder,
FieldInfo proxyInfoField,
FieldInfo fieldInterceptorField,
System.Type baseType)
{
ProxyBuilderHelper.MakeProxySerializable(typeBuilder);
ImplementDeserializationConstructor(typeBuilder, baseType);
ImplementGetObjectData(typeBuilder, proxyInfoField, fieldInterceptorField, baseType);
}

private static void ImplementDeserializationConstructor(TypeBuilder typeBuilder, System.Type parentType)
{
var parameterTypes = new[] { typeof (SerializationInfo), typeof (StreamingContext) };
Expand Down Expand Up @@ -249,7 +242,13 @@ private static void ImplementGetObjectData(TypeBuilder typeBuilder, FieldInfo pr
typeBuilder.DefineMethodOverride(methodBuilder, ProxyBuilderHelper.SerializableGetObjectDataMethod);
}

private static void ImplementGetFieldInterceptor(TypeBuilder typeBuilder, MethodInfo method, FieldInfo fieldInterceptorField)
private static void ImplementIFieldInterceptorAccessor(TypeBuilder typeBuilder, FieldInfo fieldInterceptorField)
{
ImplementGetFieldInterceptor(typeBuilder, fieldInterceptorField);
ImplementSetFieldInterceptor(typeBuilder, fieldInterceptorField);
}

private static void ImplementGetFieldInterceptor(TypeBuilder typeBuilder, FieldInfo fieldInterceptorField)
{
// get { return this.__fieldInterceptor; }

Expand All @@ -268,10 +267,10 @@ private static void ImplementGetFieldInterceptor(TypeBuilder typeBuilder, Method
IL.Emit(OpCodes.Ldfld, fieldInterceptorField);
IL.Emit(OpCodes.Ret);

typeBuilder.DefineMethodOverride(getMethod, method);
typeBuilder.DefineMethodOverride(getMethod, AccessorTypeFieldInterceptorProperty.GetMethod);
}

private static void ImplementSetFieldInterceptor(TypeBuilder typeBuilder, MethodInfo method, FieldInfo fieldInterceptorField)
private static void ImplementSetFieldInterceptor(TypeBuilder typeBuilder, FieldInfo fieldInterceptorField)
{
// set { this.__fieldInterceptor = value; }

Expand All @@ -291,7 +290,7 @@ private static void ImplementSetFieldInterceptor(TypeBuilder typeBuilder, Method
IL.Emit(OpCodes.Stfld, fieldInterceptorField);
IL.Emit(OpCodes.Ret);

typeBuilder.DefineMethodOverride(setMethod, method);
typeBuilder.DefineMethodOverride(setMethod, AccessorTypeFieldInterceptorProperty.SetMethod);
}

private static void ImplementGet(TypeBuilder typeBuilder, MethodInfo getter, FieldInfo fieldInterceptorField)
Expand Down
19 changes: 13 additions & 6 deletions src/NHibernate/Proxy/ProxyBuilderHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,22 @@ internal static void CallDefaultBaseConstructor(ILGenerator il, System.Type pare
il.Emit(OpCodes.Call, baseConstructor);
}

internal static IEnumerable<MethodInfo> GetProxiableMethods(System.Type type, IEnumerable<System.Type> interfaces)
internal static IEnumerable<MethodInfo> GetProxiableMethods(System.Type type)
{
const BindingFlags candidateMethodsBindingFlags =
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
return
type.GetMethods(candidateMethodsBindingFlags)
.Where(method => method.IsProxiable())
.Concat(interfaces.SelectMany(interfaceType => interfaceType.GetMethods()))
.Distinct();

return type.GetMethods(candidateMethodsBindingFlags).Where(m => m.IsProxiable());
}

internal static IEnumerable<MethodInfo> GetProxiableMethods(System.Type type, IEnumerable<System.Type> interfaces)
{
var proxiableMethods =
GetProxiableMethods(type)
.Concat(interfaces.SelectMany(i => i.GetMethods()))
.Distinct();

return proxiableMethods;
}

internal static void MakeProxySerializable(TypeBuilder typeBuilder)
Expand Down