|
From: <fab...@us...> - 2011-03-20 17:04:02
|
Revision: 5476
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5476&view=rev
Author: fabiomaulo
Date: 2011-03-20 17:03:52 +0000 (Sun, 20 Mar 2011)
Log Message:
-----------
"Initial" upload of embedded DynamicProxy after a little "hands on"
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/NHibernate.csproj
Added Paths:
-----------
trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/
trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/DefaultArgumentHandler.cs
trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/DefaultMethodEmitter.cs
trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/DefaultProxyMethodBuilder.cs
trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/HashSetExtensions.cs
trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IArgumentHandler.cs
trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IInterceptor.cs
trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IMethodBodyEmitter.cs
trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IProxy.cs
trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IProxyCache.cs
trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IProxyMethodBuilder.cs
trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/InterceptorHandler.cs
trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/InvocationHandler.cs
trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/InvocationInfo.cs
trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyCache.cs
trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyCacheEntry.cs
trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyDummy.cs
trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyFactory.cs
trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyImplementor.cs
trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyObjectReference.cs
Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj
===================================================================
--- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2011-03-16 14:16:50 UTC (rev 5475)
+++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2011-03-20 17:03:52 UTC (rev 5476)
@@ -326,6 +326,25 @@
<Compile Include="Properties\PascalCaseMUnderscoreStrategy.cs" />
<Compile Include="Properties\PascalCaseUnderscoreStrategy.cs" />
<Compile Include="Properties\PropertyAccessorFactory.cs" />
+ <Compile Include="Proxy\DynamicProxy\DefaultArgumentHandler.cs" />
+ <Compile Include="Proxy\DynamicProxy\DefaultMethodEmitter.cs" />
+ <Compile Include="Proxy\DynamicProxy\DefaultProxyMethodBuilder.cs" />
+ <Compile Include="Proxy\DynamicProxy\HashSetExtensions.cs" />
+ <Compile Include="Proxy\DynamicProxy\IArgumentHandler.cs" />
+ <Compile Include="Proxy\DynamicProxy\IInterceptor.cs" />
+ <Compile Include="Proxy\DynamicProxy\IMethodBodyEmitter.cs" />
+ <Compile Include="Proxy\DynamicProxy\InterceptorHandler.cs" />
+ <Compile Include="Proxy\DynamicProxy\InvocationHandler.cs" />
+ <Compile Include="Proxy\DynamicProxy\InvocationInfo.cs" />
+ <Compile Include="Proxy\DynamicProxy\IProxy.cs" />
+ <Compile Include="Proxy\DynamicProxy\IProxyCache.cs" />
+ <Compile Include="Proxy\DynamicProxy\IProxyMethodBuilder.cs" />
+ <Compile Include="Proxy\DynamicProxy\ProxyCache.cs" />
+ <Compile Include="Proxy\DynamicProxy\ProxyCacheEntry.cs" />
+ <Compile Include="Proxy\DynamicProxy\ProxyDummy.cs" />
+ <Compile Include="Proxy\DynamicProxy\ProxyFactory.cs" />
+ <Compile Include="Proxy\DynamicProxy\ProxyImplementor.cs" />
+ <Compile Include="Proxy\DynamicProxy\ProxyObjectReference.cs" />
<Compile Include="Proxy\INHibernateProxy.cs" />
<Compile Include="Proxy\IProxyFactory.cs" />
<Compile Include="Proxy\AbstractLazyInitializer.cs" />
Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/DefaultArgumentHandler.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/DefaultArgumentHandler.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/DefaultArgumentHandler.cs 2011-03-20 17:03:52 UTC (rev 5476)
@@ -0,0 +1,74 @@
+#region Credits
+
+// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project.
+// The license is the same of NHibernate license (LGPL Version 2.1, February 1999).
+// The source was then modified to be the default DynamicProxy of NHibernate project.
+
+#endregion
+
+using System;
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace NHibernate.Proxy.DynamicProxy
+{
+ internal class DefaultArgumentHandler : IArgumentHandler
+ {
+ #region IArgumentHandler Members
+
+ public void PushArguments(ParameterInfo[] methodParameters, ILGenerator IL, bool isStatic)
+ {
+ ParameterInfo[] parameters = methodParameters ?? new ParameterInfo[0];
+ int parameterCount = parameters.Length;
+
+ // object[] args = new object[size];
+ IL.Emit(OpCodes.Ldc_I4, parameterCount);
+ IL.Emit(OpCodes.Newarr, typeof (object));
+ IL.Emit(OpCodes.Stloc_S, 0);
+
+ if (parameterCount == 0)
+ {
+ IL.Emit(OpCodes.Ldloc_S, 0);
+ return;
+ }
+
+ // Populate the object array with the list of arguments
+ int index = 0;
+ int argumentPosition = 1;
+ foreach (ParameterInfo param in parameters)
+ {
+ System.Type parameterType = param.ParameterType;
+ // args[N] = argumentN (pseudocode)
+ IL.Emit(OpCodes.Ldloc_S, 0);
+ IL.Emit(OpCodes.Ldc_I4, index);
+
+ // Zero out the [out] parameters
+ if (param.IsOut)
+ {
+ IL.Emit(OpCodes.Ldnull);
+ IL.Emit(OpCodes.Stelem_Ref);
+ argumentPosition++;
+ index++;
+ continue;
+ }
+
+ IL.Emit(OpCodes.Ldarg, argumentPosition);
+
+ bool isGeneric = parameterType.IsGenericParameter;
+
+ if (parameterType.IsValueType || isGeneric)
+ {
+ IL.Emit(OpCodes.Box, parameterType);
+ }
+
+ IL.Emit(OpCodes.Stelem_Ref);
+
+ index++;
+ argumentPosition++;
+ }
+ IL.Emit(OpCodes.Ldloc_S, 0);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/DefaultMethodEmitter.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/DefaultMethodEmitter.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/DefaultMethodEmitter.cs 2011-03-20 17:03:52 UTC (rev 5476)
@@ -0,0 +1,240 @@
+#region Credits
+
+// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project.
+// The license is the same of NHibernate license (LGPL Version 2.1, February 1999).
+// The source was then modified to be the default DynamicProxy of NHibernate project.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace NHibernate.Proxy.DynamicProxy
+{
+ internal class DefaultMethodEmitter : IMethodBodyEmitter
+ {
+ private static readonly MethodInfo getInterceptor;
+
+ private static readonly MethodInfo getGenericMethodFromHandle = typeof (MethodBase).GetMethod("GetMethodFromHandle",
+ BindingFlags.Public | BindingFlags.Static, null,
+ new[] {typeof (RuntimeMethodHandle), typeof (RuntimeTypeHandle)}, null);
+
+ private static readonly MethodInfo getMethodFromHandle = typeof (MethodBase).GetMethod("GetMethodFromHandle", new[] {typeof (RuntimeMethodHandle)});
+ private static readonly MethodInfo getTypeFromHandle = typeof(System.Type).GetMethod("GetTypeFromHandle");
+ private static readonly MethodInfo handlerMethod = typeof (IInterceptor).GetMethod("Intercept");
+ private static readonly ConstructorInfo infoConstructor;
+ private static readonly PropertyInfo interceptorProperty = typeof (IProxy).GetProperty("Interceptor");
+
+ private static readonly ConstructorInfo notImplementedConstructor = typeof(NotImplementedException).GetConstructor(new System.Type[0]);
+
+ private static readonly Dictionary<string, OpCode> stindMap = new Dictionary<string, OpCode>();
+ private readonly IArgumentHandler _argumentHandler;
+
+ static DefaultMethodEmitter()
+ {
+ getInterceptor = interceptorProperty.GetGetMethod();
+ var constructorTypes = new[]
+ {
+ typeof (object), typeof (MethodInfo),
+ typeof (StackTrace), typeof (System.Type[]), typeof (object[])
+ };
+
+ infoConstructor = typeof (InvocationInfo).GetConstructor(constructorTypes);
+
+
+ stindMap["Bool&"] = OpCodes.Stind_I1;
+ stindMap["Int8&"] = OpCodes.Stind_I1;
+ stindMap["Uint8&"] = OpCodes.Stind_I1;
+
+ stindMap["Int16&"] = OpCodes.Stind_I2;
+ stindMap["Uint16&"] = OpCodes.Stind_I2;
+
+ stindMap["Uint32&"] = OpCodes.Stind_I4;
+ stindMap["Int32&"] = OpCodes.Stind_I4;
+
+ stindMap["IntPtr"] = OpCodes.Stind_I4;
+ stindMap["Uint64&"] = OpCodes.Stind_I8;
+ stindMap["Int64&"] = OpCodes.Stind_I8;
+ stindMap["Float32&"] = OpCodes.Stind_R4;
+ stindMap["Float64&"] = OpCodes.Stind_R8;
+ }
+
+ public DefaultMethodEmitter() : this(new DefaultArgumentHandler()) {}
+
+ public DefaultMethodEmitter(IArgumentHandler argumentHandler)
+ {
+ _argumentHandler = argumentHandler;
+ }
+
+ #region IMethodBodyEmitter Members
+
+ public void EmitMethodBody(ILGenerator IL, MethodInfo method, FieldInfo field)
+ {
+ ParameterInfo[] parameters = method.GetParameters();
+ IL.DeclareLocal(typeof (object[]));
+ IL.DeclareLocal(typeof (InvocationInfo));
+ IL.DeclareLocal(typeof(System.Type[]));
+
+ IL.Emit(OpCodes.Ldarg_0);
+ IL.Emit(OpCodes.Callvirt, getInterceptor);
+
+ // if (interceptor == null)
+ // throw new NullReferenceException();
+
+ Label skipThrow = IL.DefineLabel();
+
+ IL.Emit(OpCodes.Dup);
+ IL.Emit(OpCodes.Ldnull);
+ IL.Emit(OpCodes.Bne_Un, skipThrow);
+
+ IL.Emit(OpCodes.Newobj, notImplementedConstructor);
+ IL.Emit(OpCodes.Throw);
+
+ IL.MarkLabel(skipThrow);
+ // Push the 'this' pointer onto the stack
+ IL.Emit(OpCodes.Ldarg_0);
+
+ // Push the MethodInfo onto the stack
+ System.Type declaringType = method.DeclaringType;
+
+ IL.Emit(OpCodes.Ldtoken, method);
+ if (declaringType.IsGenericType)
+ {
+ IL.Emit(OpCodes.Ldtoken, declaringType);
+ IL.Emit(OpCodes.Call, getGenericMethodFromHandle);
+ }
+ else
+ {
+ IL.Emit(OpCodes.Call, getMethodFromHandle);
+ }
+
+ IL.Emit(OpCodes.Castclass, typeof (MethodInfo));
+
+ PushStackTrace(IL);
+ PushGenericArguments(method, IL);
+ _argumentHandler.PushArguments(parameters, IL, false);
+
+ // InvocationInfo info = new InvocationInfo(...);
+
+ IL.Emit(OpCodes.Newobj, infoConstructor);
+ IL.Emit(OpCodes.Stloc_1);
+ IL.Emit(OpCodes.Ldloc_1);
+ IL.Emit(OpCodes.Callvirt, handlerMethod);
+
+ SaveRefArguments(IL, parameters);
+ PackageReturnType(method, IL);
+
+ IL.Emit(OpCodes.Ret);
+ }
+
+ #endregion
+
+ private static void SaveRefArguments(ILGenerator IL, ParameterInfo[] parameters)
+ {
+ // Save the arguments returned from the handler method
+ MethodInfo getArguments = typeof (InvocationInfo).GetMethod("get_Arguments");
+ IL.Emit(OpCodes.Ldloc_1);
+ IL.Emit(OpCodes.Call, getArguments);
+ IL.Emit(OpCodes.Stloc_0);
+
+ foreach (ParameterInfo param in parameters)
+ {
+ string typeName = param.ParameterType.Name;
+
+ bool isRef = param.ParameterType.IsByRef && typeName.EndsWith("&");
+ if (!isRef)
+ {
+ continue;
+ }
+
+ // Load the destination address
+ IL.Emit(OpCodes.Ldarg, param.Position + 1);
+
+ // Load the argument value
+ IL.Emit(OpCodes.Ldloc_0);
+ IL.Emit(OpCodes.Ldc_I4, param.Position);
+ IL.Emit(OpCodes.Ldelem_Ref);
+
+ typeName = typeName.Replace("&", "");
+ System.Type unboxedType = System.Type.GetType(typeName);
+
+ IL.Emit(OpCodes.Unbox_Any, unboxedType);
+
+ OpCode stind = GetStindInstruction(param.ParameterType);
+ IL.Emit(stind);
+ }
+ }
+
+ private static OpCode GetStindInstruction(System.Type parameterType)
+ {
+ if (parameterType.IsClass && !parameterType.Name.EndsWith("&"))
+ {
+ return OpCodes.Stind_Ref;
+ }
+
+
+ string typeName = parameterType.Name;
+
+ if (!stindMap.ContainsKey(typeName) && parameterType.IsByRef)
+ {
+ return OpCodes.Stind_Ref;
+ }
+
+ Debug.Assert(stindMap.ContainsKey(typeName));
+ OpCode result = stindMap[typeName];
+
+ return result;
+ }
+
+ private void PushStackTrace(ILGenerator IL)
+ {
+ // NOTE: The stack trace has been disabled for performance reasons
+ IL.Emit(OpCodes.Ldnull);
+ }
+
+ private void PushGenericArguments(MethodInfo method, ILGenerator IL)
+ {
+ System.Type[] typeParameters = method.GetGenericArguments();
+
+ // If this is a generic method, we need to store
+ // the generic method arguments
+ int genericTypeCount = typeParameters.Length;
+
+ // Type[] genericTypeArgs = new Type[genericTypeCount];
+ IL.Emit(OpCodes.Ldc_I4, genericTypeCount);
+ IL.Emit(OpCodes.Newarr, typeof(System.Type));
+
+ if (genericTypeCount == 0)
+ {
+ return;
+ }
+
+ for (int index = 0; index < genericTypeCount; index++)
+ {
+ System.Type currentType = typeParameters[index];
+
+ IL.Emit(OpCodes.Dup);
+ IL.Emit(OpCodes.Ldc_I4, index);
+ IL.Emit(OpCodes.Ldtoken, currentType);
+ IL.Emit(OpCodes.Call, getTypeFromHandle);
+ IL.Emit(OpCodes.Stelem_Ref);
+ }
+ }
+
+ private void PackageReturnType(MethodInfo method, ILGenerator IL)
+ {
+ System.Type returnType = method.ReturnType;
+ // Unbox the return value if necessary
+ if (returnType == typeof (void))
+ {
+ IL.Emit(OpCodes.Pop);
+ return;
+ }
+
+ IL.Emit(OpCodes.Unbox_Any, returnType);
+ }
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/DefaultProxyMethodBuilder.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/DefaultProxyMethodBuilder.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/DefaultProxyMethodBuilder.cs 2011-03-20 17:03:52 UTC (rev 5476)
@@ -0,0 +1,67 @@
+#region Credits
+
+// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project.
+// The license is the same of NHibernate license (LGPL Version 2.1, February 1999).
+// The source was then modified to be the default DynamicProxy of NHibernate project.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace NHibernate.Proxy.DynamicProxy
+{
+ internal class DefaultyProxyMethodBuilder : IProxyMethodBuilder
+ {
+ public DefaultyProxyMethodBuilder() : this(new DefaultMethodEmitter()) {}
+
+ public DefaultyProxyMethodBuilder(IMethodBodyEmitter emitter)
+ {
+ if (emitter == null)
+ {
+ throw new ArgumentNullException("emitter");
+ }
+ MethodBodyEmitter = emitter;
+ }
+
+ public IMethodBodyEmitter MethodBodyEmitter { get; private set; }
+
+ #region IProxyMethodBuilder Members
+
+ public void CreateProxiedMethod(FieldInfo field, MethodInfo method, TypeBuilder typeBuilder)
+ {
+ const MethodAttributes methodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig |
+ MethodAttributes.Virtual;
+ ParameterInfo[] parameters = method.GetParameters();
+
+ MethodBuilder methodBuilder = typeBuilder.DefineMethod(method.Name, methodAttributes,
+ CallingConventions.HasThis, method.ReturnType,
+ parameters.Select(param => param.ParameterType).ToArray());
+
+ System.Type[] typeArgs = method.GetGenericArguments();
+
+ if (typeArgs.Length > 0)
+ {
+ var typeNames = new List<string>();
+
+ for (int index = 0; index < typeArgs.Length; index++)
+ {
+ typeNames.Add(string.Format("T{0}", index));
+ }
+
+ methodBuilder.DefineGenericParameters(typeNames.ToArray());
+ }
+
+ ILGenerator IL = methodBuilder.GetILGenerator();
+
+ Debug.Assert(MethodBodyEmitter != null);
+ MethodBodyEmitter.EmitMethodBody(IL, method, field);
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/HashSetExtensions.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/HashSetExtensions.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/HashSetExtensions.cs 2011-03-20 17:03:52 UTC (rev 5476)
@@ -0,0 +1,16 @@
+using System.Collections.Generic;
+
+namespace NHibernate.Proxy.DynamicProxy
+{
+ public static class HashSetExtensions
+ {
+ public static HashSet<T> Merge<T>(this HashSet<T> source, IEnumerable<T> toMerge)
+ {
+ foreach (T item in toMerge)
+ {
+ source.Add(item);
+ }
+ return source;
+ }
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IArgumentHandler.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IArgumentHandler.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IArgumentHandler.cs 2011-03-20 17:03:52 UTC (rev 5476)
@@ -0,0 +1,18 @@
+#region Credits
+
+// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project.
+// The license is the same of NHibernate license (LGPL Version 2.1, February 1999).
+// The source was then modified to be the default DynamicProxy of NHibernate project.
+
+#endregion
+
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace NHibernate.Proxy.DynamicProxy
+{
+ public interface IArgumentHandler
+ {
+ void PushArguments(ParameterInfo[] parameters, ILGenerator IL, bool isStatic);
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IInterceptor.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IInterceptor.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IInterceptor.cs 2011-03-20 17:03:52 UTC (rev 5476)
@@ -0,0 +1,15 @@
+#region Credits
+
+// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project.
+// The license is the same of NHibernate license (LGPL Version 2.1, February 1999).
+// The source was then modified to be the default DynamicProxy of NHibernate project.
+
+#endregion
+
+namespace NHibernate.Proxy.DynamicProxy
+{
+ public interface IInterceptor
+ {
+ object Intercept(InvocationInfo info);
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IMethodBodyEmitter.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IMethodBodyEmitter.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IMethodBodyEmitter.cs 2011-03-20 17:03:52 UTC (rev 5476)
@@ -0,0 +1,18 @@
+#region Credits
+
+// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project.
+// The license is the same of NHibernate license (LGPL Version 2.1, February 1999).
+// The source was then modified to be the default DynamicProxy of NHibernate project.
+
+#endregion
+
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace NHibernate.Proxy.DynamicProxy
+{
+ public interface IMethodBodyEmitter
+ {
+ void EmitMethodBody(ILGenerator IL, MethodInfo method, FieldInfo field);
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IProxy.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IProxy.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IProxy.cs 2011-03-20 17:03:52 UTC (rev 5476)
@@ -0,0 +1,15 @@
+#region Credits
+
+// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project.
+// The license is the same of NHibernate license (LGPL Version 2.1, February 1999).
+// The source was then modified to be the default DynamicProxy of NHibernate project.
+
+#endregion
+
+namespace NHibernate.Proxy.DynamicProxy
+{
+ public interface IProxy
+ {
+ IInterceptor Interceptor { get; set; }
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IProxyCache.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IProxyCache.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IProxyCache.cs 2011-03-20 17:03:52 UTC (rev 5476)
@@ -0,0 +1,19 @@
+#region Credits
+
+// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project.
+// The license is the same of NHibernate license (LGPL Version 2.1, February 1999).
+// The source was then modified to be the default DynamicProxy of NHibernate project.
+
+#endregion
+
+using System;
+
+namespace NHibernate.Proxy.DynamicProxy
+{
+ public interface IProxyCache
+ {
+ bool Contains(System.Type baseType, params System.Type[] baseInterfaces);
+ System.Type GetProxyType(System.Type baseType, params System.Type[] baseInterfaces);
+ void StoreProxyType(System.Type result, System.Type baseType, params System.Type[] baseInterfaces);
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IProxyMethodBuilder.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IProxyMethodBuilder.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/IProxyMethodBuilder.cs 2011-03-20 17:03:52 UTC (rev 5476)
@@ -0,0 +1,18 @@
+#region Credits
+
+// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project.
+// The license is the same of NHibernate license (LGPL Version 2.1, February 1999).
+// The source was then modified to be the default DynamicProxy of NHibernate project.
+
+#endregion
+
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace NHibernate.Proxy.DynamicProxy
+{
+ public interface IProxyMethodBuilder
+ {
+ void CreateProxiedMethod(FieldInfo field, MethodInfo method, TypeBuilder typeBuilder);
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/InterceptorHandler.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/InterceptorHandler.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/InterceptorHandler.cs 2011-03-20 17:03:52 UTC (rev 5476)
@@ -0,0 +1,17 @@
+#region Credits
+
+// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project.
+// The license is the same of NHibernate license (LGPL Version 2.1, February 1999).
+// The source was then modified to be the default DynamicProxy of NHibernate project.
+
+#endregion
+
+using System;
+using System.Diagnostics;
+using System.Reflection;
+
+namespace NHibernate.Proxy.DynamicProxy
+{
+ public delegate object InterceptorHandler(object proxy, MethodInfo targetMethod,
+ StackTrace trace, System.Type[] genericTypeArgs, object[] args);
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/InvocationHandler.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/InvocationHandler.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/InvocationHandler.cs 2011-03-20 17:03:52 UTC (rev 5476)
@@ -0,0 +1,12 @@
+#region Credits
+
+// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project.
+// The license is the same of NHibernate license (LGPL Version 2.1, February 1999).
+// The source was then modified to be the default DynamicProxy of NHibernate project.
+
+#endregion
+
+namespace NHibernate.Proxy.DynamicProxy
+{
+ public delegate object InvocationHandler(InvocationInfo info);
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/InvocationInfo.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/InvocationInfo.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/InvocationInfo.cs 2011-03-20 17:03:52 UTC (rev 5476)
@@ -0,0 +1,109 @@
+#region Credits
+
+// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project.
+// The license is the same of NHibernate license (LGPL Version 2.1, February 1999).
+// The source was then modified to be the default DynamicProxy of NHibernate project.
+
+#endregion
+
+using System;
+using System.Diagnostics;
+using System.Reflection;
+using System.Text;
+
+namespace NHibernate.Proxy.DynamicProxy
+{
+ public class InvocationInfo
+ {
+ private readonly object[] args;
+ private readonly object proxy;
+ private readonly MethodInfo targetMethod;
+ private readonly StackTrace trace;
+ private readonly System.Type[] typeArgs;
+
+ public InvocationInfo(object proxy, MethodInfo targetMethod,
+ StackTrace trace, System.Type[] genericTypeArgs, object[] args)
+ {
+ this.proxy = proxy;
+ this.targetMethod = targetMethod;
+ typeArgs = genericTypeArgs;
+ this.args = args;
+ this.trace = trace;
+ }
+
+ public object Target
+ {
+ get { return proxy; }
+ }
+
+ public MethodInfo TargetMethod
+ {
+ get { return targetMethod; }
+ }
+
+ public StackTrace StackTrace
+ {
+ get { return trace; }
+ }
+
+ public System.Type[] TypeArguments
+ {
+ get { return typeArgs; }
+ }
+
+ public object[] Arguments
+ {
+ get { return args; }
+ }
+
+ public void SetArgument(int position, object arg)
+ {
+ args[position] = arg;
+ }
+
+ public override string ToString()
+ {
+ var builder = new StringBuilder();
+ builder.AppendFormat("Target Method:{0,30:G}\n", GetMethodName(targetMethod));
+ builder.AppendLine("Arguments:");
+
+ foreach (ParameterInfo info in targetMethod.GetParameters())
+ {
+ object currentArgument = args[info.Position];
+ if (currentArgument == null)
+ {
+ currentArgument = "(null)";
+ }
+ builder.AppendFormat("\t{0,10:G}: {1}\n", info.Name, currentArgument);
+ }
+ builder.AppendLine();
+
+ return builder.ToString();
+ }
+
+ private string GetMethodName(MethodInfo method)
+ {
+ var builder = new StringBuilder(512);
+ builder.AppendFormat("{0}.{1}", method.DeclaringType.Name, method.Name);
+ builder.Append("(");
+
+ ParameterInfo[] parameters = method.GetParameters();
+ int parameterCount = parameters.Length;
+
+ int index = 0;
+ foreach (ParameterInfo param in parameters)
+ {
+ index++;
+ builder.AppendFormat("{0} {1}", param.ParameterType.Name, param.Name);
+
+ if (index < parameterCount)
+ {
+ builder.Append(", ");
+ }
+ }
+ builder.Append(")");
+
+ return builder.ToString();
+ }
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyCache.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyCache.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyCache.cs 2011-03-20 17:03:52 UTC (rev 5476)
@@ -0,0 +1,52 @@
+#region Credits
+
+// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project.
+// The license is the same of NHibernate license (LGPL Version 2.1, February 1999).
+// The source was then modified to be the default DynamicProxy of NHibernate project.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+
+namespace NHibernate.Proxy.DynamicProxy
+{
+ public class ProxyCache : IProxyCache
+ {
+ private readonly Dictionary<ProxyCacheEntry, System.Type> cache = new Dictionary<ProxyCacheEntry, System.Type>();
+ private readonly object syncObject = new object();
+
+ #region IProxyCache Members
+
+ public bool Contains(System.Type baseType, params System.Type[] baseInterfaces)
+ {
+ if (baseType == null)
+ {
+ return false;
+ }
+
+ var entry = new ProxyCacheEntry(baseType, baseInterfaces);
+ return cache.ContainsKey(entry);
+ }
+
+ public System.Type GetProxyType(System.Type baseType, params System.Type[] baseInterfaces)
+ {
+ lock (syncObject)
+ {
+ var entry = new ProxyCacheEntry(baseType, baseInterfaces);
+ return cache[entry];
+ }
+ }
+
+ public void StoreProxyType(System.Type result, System.Type baseType, params System.Type[] baseInterfaces)
+ {
+ lock (syncObject)
+ {
+ var entry = new ProxyCacheEntry(baseType, baseInterfaces);
+ cache[entry] = result;
+ }
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyCacheEntry.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyCacheEntry.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyCacheEntry.cs 2011-03-20 17:03:52 UTC (rev 5476)
@@ -0,0 +1,62 @@
+#region Credits
+
+// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project.
+// The license is the same of NHibernate license (LGPL Version 2.1, February 1999).
+// The source was then modified to be the default DynamicProxy of NHibernate project.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+
+namespace NHibernate.Proxy.DynamicProxy
+{
+ [Serializable]
+ public class ProxyCacheEntry
+ {
+ private readonly int hashCode;
+
+ public ProxyCacheEntry(System.Type baseType, System.Type[] interfaces)
+ {
+ if (baseType == null)
+ {
+ throw new ArgumentNullException("baseType");
+ }
+ BaseType = baseType;
+ Interfaces = interfaces ?? new System.Type[0];
+
+ if (Interfaces.Length == 0)
+ {
+ hashCode = baseType.GetHashCode();
+ return;
+ }
+
+ // duplicated type exclusion
+ var set = new HashSet<System.Type>(Interfaces) { baseType };
+ hashCode = 59;
+ foreach (System.Type type in set)
+ {
+ hashCode ^= type.GetHashCode();
+ }
+ }
+
+ public System.Type BaseType { get; private set; }
+ public System.Type[] Interfaces { get; private set; }
+
+ public override bool Equals(object obj)
+ {
+ var that = obj as ProxyCacheEntry;
+ if (ReferenceEquals(null, that))
+ {
+ return false;
+ }
+
+ return hashCode == that.GetHashCode();
+ }
+
+ public override int GetHashCode()
+ {
+ return hashCode;
+ }
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyDummy.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyDummy.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyDummy.cs 2011-03-20 17:03:52 UTC (rev 5476)
@@ -0,0 +1,15 @@
+#region Credits
+
+// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project.
+// The license is the same of NHibernate license (LGPL Version 2.1, February 1999).
+// The source was then modified to be the default DynamicProxy of NHibernate project.
+
+#endregion
+
+namespace NHibernate.Proxy.DynamicProxy
+{
+ public class ProxyDummy
+ {
+ /* No Implementation */
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyFactory.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyFactory.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyFactory.cs 2011-03-20 17:03:52 UTC (rev 5476)
@@ -0,0 +1,306 @@
+#region Credits
+
+// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project.
+// The license is the same of NHibernate license (LGPL Version 2.1, February 1999).
+// The source was then modified to be the default DynamicProxy of NHibernate project.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.Serialization;
+
+namespace NHibernate.Proxy.DynamicProxy
+{
+ public sealed class ProxyFactory
+ {
+ private static readonly ConstructorInfo baseConstructor = typeof(object).GetConstructor(new System.Type[0]);
+ private static readonly MethodInfo getTypeFromHandle = typeof(System.Type).GetMethod("GetTypeFromHandle");
+
+ private static readonly MethodInfo getValue = typeof (SerializationInfo).GetMethod("GetValue", BindingFlags.Public | BindingFlags.Instance, null,
+ new[] { typeof(string), typeof(System.Type) }, null);
+
+ private static readonly MethodInfo setType = typeof(SerializationInfo).GetMethod("SetType", BindingFlags.Public | BindingFlags.Instance, null, new[] { typeof(System.Type) }, null);
+
+ private static readonly MethodInfo addValue = typeof (SerializationInfo).GetMethod("AddValue", BindingFlags.Public | BindingFlags.Instance, null,
+ new[] {typeof (string), typeof (object)}, null);
+
+ public ProxyFactory()
+ : this(new DefaultyProxyMethodBuilder()) {}
+
+ public ProxyFactory(IProxyMethodBuilder proxyMethodBuilder)
+ {
+ if (proxyMethodBuilder == null)
+ {
+ throw new ArgumentNullException("proxyMethodBuilder");
+ }
+ ProxyMethodBuilder = proxyMethodBuilder;
+ Cache = new ProxyCache();
+ }
+
+ public IProxyCache Cache { get; private set; }
+
+ public IProxyMethodBuilder ProxyMethodBuilder { get; private set; }
+
+ public object CreateProxy(System.Type instanceType, IInterceptor interceptor, params System.Type[] baseInterfaces)
+ {
+ System.Type proxyType = CreateProxyType(instanceType, baseInterfaces);
+ object result = Activator.CreateInstance(proxyType);
+ var proxy = (IProxy) result;
+ proxy.Interceptor = interceptor;
+
+ return result;
+ }
+
+ public System.Type CreateProxyType(System.Type baseType, params System.Type[] interfaces)
+ {
+ System.Type[] baseInterfaces = ReferenceEquals(null, interfaces) ? new System.Type[0] : interfaces.Where(t => t != null).ToArray();
+ // Reuse the previous results, if possible
+ if (Cache.Contains(baseType, baseInterfaces))
+ {
+ return Cache.GetProxyType(baseType, baseInterfaces);
+ }
+
+ System.Type result = CreateUncachedProxyType(baseType, baseInterfaces);
+
+ // Cache the proxy type
+ if (result != null && Cache != null)
+ {
+ Cache.StoreProxyType(result, baseType, baseInterfaces);
+ }
+
+ return result;
+ }
+
+ private System.Type CreateUncachedProxyType(System.Type baseType, System.Type[] baseInterfaces)
+ {
+ AppDomain currentDomain = AppDomain.CurrentDomain;
+ string typeName = string.Format("{0}Proxy", baseType.Name);
+ string assemblyName = string.Format("{0}Assembly", typeName);
+ string moduleName = string.Format("{0}Module", typeName);
+
+ var name = new AssemblyName(assemblyName);
+#if DEBUG
+ AssemblyBuilderAccess access = AssemblyBuilderAccess.RunAndSave;
+#else
+ AssemblyBuilderAccess access = AssemblyBuilderAccess.Run;
+#endif
+ AssemblyBuilder assemblyBuilder = currentDomain.DefineDynamicAssembly(name, access);
+
+#if DEBUG
+ ModuleBuilder moduleBuilder =
+ assemblyBuilder.DefineDynamicModule(moduleName, string.Format("{0}.mod", moduleName), true);
+#else
+ ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(moduleName);
+#endif
+
+ TypeAttributes typeAttributes = TypeAttributes.AutoClass | TypeAttributes.Class |
+ TypeAttributes.Public | TypeAttributes.BeforeFieldInit;
+
+ var interfaces = new HashSet<System.Type>();
+ interfaces.Merge(baseInterfaces);
+
+ // Use the proxy dummy as the base type
+ // since we're not inheriting from any class type
+ System.Type parentType = baseType;
+ if (baseType.IsInterface)
+ {
+ parentType = typeof (ProxyDummy);
+ interfaces.Add(baseType);
+ }
+
+ // Add any inherited interfaces
+ System.Type[] computedInterfaces = interfaces.ToArray();
+ foreach (System.Type interfaceType in computedInterfaces)
+ {
+ interfaces.Merge(GetInterfaces(interfaceType));
+ }
+
+ // Add the ISerializable interface so that it can be implemented
+ interfaces.Add(typeof (ISerializable));
+
+ TypeBuilder typeBuilder = moduleBuilder.DefineType(typeName, typeAttributes, parentType, interfaces.ToArray());
+
+ ConstructorBuilder defaultConstructor = DefineConstructor(typeBuilder);
+
+ // Implement IProxy
+ var implementor = new ProxyImplementor();
+ implementor.ImplementProxy(typeBuilder);
+
+ FieldInfo interceptorField = implementor.InterceptorField;
+
+ // Provide a custom implementation of ISerializable
+ // instead of redirecting it back to the interceptor
+ foreach (MethodInfo method in GetProxiableMethods(baseType, interfaces).Where(method => method.DeclaringType != typeof(ISerializable)))
+ {
+ ProxyMethodBuilder.CreateProxiedMethod(interceptorField, method, typeBuilder);
+ }
+
+ // Make the proxy serializable
+ AddSerializationSupport(baseType, baseInterfaces, typeBuilder, interceptorField, defaultConstructor);
+ System.Type proxyType = typeBuilder.CreateType();
+
+#if DEBUG_PROXY_OUTPUT
+ assemblyBuilder.Save("generatedAssembly.dll");
+#endif
+ return proxyType;
+ }
+
+ private IEnumerable<System.Type> GetInterfaces(System.Type currentType)
+ {
+ return GetAllInterfaces(currentType);
+ }
+
+ private IEnumerable<System.Type> GetAllInterfaces(System.Type currentType)
+ {
+ System.Type[] interfaces = currentType.GetInterfaces();
+
+ foreach (System.Type current in interfaces)
+ {
+ yield return current;
+ foreach (System.Type @interface in GetAllInterfaces(current))
+ {
+ yield return @interface;
+ }
+ }
+ }
+
+ private IEnumerable<MethodInfo> GetProxiableMethods(System.Type type, IEnumerable<System.Type> interfaces)
+ {
+ const BindingFlags candidateMethodsBindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
+ return
+ type.GetMethods(candidateMethodsBindingFlags)
+ .Where(method => IsProxiable(method))
+ .Concat(interfaces.SelectMany(interfaceType => interfaceType.GetMethods())).Distinct();
+ }
+
+ private bool IsProxiable(MethodInfo method)
+ {
+ return (((method.IsPublic || method.IsFamily || method.IsAssembly || method.IsFamilyOrAssembly)
+ && (method.IsVirtual || method.IsAbstract))
+ && (method.DeclaringType != typeof(MarshalByRefObject)))
+ && (method.DeclaringType != typeof(object) || !"finalize".Equals(method.Name.ToLowerInvariant()));
+ }
+
+ private static ConstructorBuilder DefineConstructor(TypeBuilder typeBuilder)
+ {
+ const MethodAttributes constructorAttributes = MethodAttributes.Public |
+ MethodAttributes.HideBySig | MethodAttributes.SpecialName |
+ MethodAttributes.RTSpecialName;
+
+ ConstructorBuilder constructor =
+ typeBuilder.DefineConstructor(constructorAttributes, CallingConventions.Standard, new System.Type[0]);
+
+ ILGenerator IL = constructor.GetILGenerator();
+
+ constructor.SetImplementationFlags(MethodImplAttributes.IL | MethodImplAttributes.Managed);
+
+ IL.Emit(OpCodes.Ldarg_0);
+ IL.Emit(OpCodes.Call, baseConstructor);
+ IL.Emit(OpCodes.Ret);
+
+ return constructor;
+ }
+
+ private static void ImplementGetObjectData(System.Type baseType, System.Type[] baseInterfaces, TypeBuilder typeBuilder, FieldInfo interceptorField)
+ {
+ const MethodAttributes attributes = MethodAttributes.Public | MethodAttributes.HideBySig |
+ MethodAttributes.Virtual;
+ var parameterTypes = new[] {typeof (SerializationInfo), typeof (StreamingContext)};
+
+ MethodBuilder methodBuilder =
+ typeBuilder.DefineMethod("GetObjectData", attributes, typeof (void), parameterTypes);
+
+ ILGenerator IL = methodBuilder.GetILGenerator();
+ //LocalBuilder proxyBaseType = IL.DeclareLocal(typeof(Type));
+
+ // info.SetType(typeof(ProxyObjectReference));
+ IL.Emit(OpCodes.Ldarg_1);
+ IL.Emit(OpCodes.Ldtoken, typeof (ProxyObjectReference));
+ IL.Emit(OpCodes.Call, getTypeFromHandle);
+ IL.Emit(OpCodes.Callvirt, setType);
+
+ // info.AddValue("__interceptor", __interceptor);
+ IL.Emit(OpCodes.Ldarg_1);
+ IL.Emit(OpCodes.Ldstr, "__interceptor");
+ IL.Emit(OpCodes.Ldarg_0);
+ IL.Emit(OpCodes.Ldfld, interceptorField);
+ IL.Emit(OpCodes.Callvirt, addValue);
+
+ IL.Emit(OpCodes.Ldarg_1);
+ IL.Emit(OpCodes.Ldstr, "__baseType");
+ IL.Emit(OpCodes.Ldstr, baseType.AssemblyQualifiedName);
+ IL.Emit(OpCodes.Callvirt, addValue);
+
+ int baseInterfaceCount = baseInterfaces.Length;
+
+ // Save the number of base interfaces
+ IL.Emit(OpCodes.Ldarg_1);
+ IL.Emit(OpCodes.Ldstr, "__baseInterfaceCount");
+ IL.Emit(OpCodes.Ldc_I4, baseInterfaceCount);
+ IL.Emit(OpCodes.Box, typeof (Int32));
+ IL.Emit(OpCodes.Callvirt, addValue);
+
+ int index = 0;
+ foreach (System.Type baseInterface in baseInterfaces)
+ {
+ IL.Emit(OpCodes.Ldarg_1);
+ IL.Emit(OpCodes.Ldstr, string.Format("__baseInterface{0}", index++));
+ IL.Emit(OpCodes.Ldstr, baseInterface.AssemblyQualifiedName);
+ IL.Emit(OpCodes.Callvirt, addValue);
+ }
+
+ IL.Emit(OpCodes.Ret);
+ }
+
+ private static void DefineSerializationConstructor(TypeBuilder typeBuilder, FieldInfo interceptorField, ConstructorBuilder defaultConstructor)
+ {
+ const MethodAttributes constructorAttributes = MethodAttributes.Public |
+ MethodAttributes.HideBySig | MethodAttributes.SpecialName |
+ MethodAttributes.RTSpecialName;
+
+ var parameterTypes = new[] {typeof (SerializationInfo), typeof (StreamingContext)};
+ ConstructorBuilder constructor = typeBuilder.DefineConstructor(constructorAttributes,
+ CallingConventions.Standard, parameterTypes);
+
+ ILGenerator IL = constructor.GetILGenerator();
+
+ LocalBuilder interceptorType = IL.DeclareLocal(typeof(System.Type));
+ //LocalBuilder interceptor = IL.DeclareLocal(typeof(IInterceptor));
+
+ constructor.SetImplementationFlags(MethodImplAttributes.IL | MethodImplAttributes.Managed);
+
+
+ IL.Emit(OpCodes.Ldtoken, typeof (IInterceptor));
+ IL.Emit(OpCodes.Call, getTypeFromHandle);
+ IL.Emit(OpCodes.Stloc, interceptorType);
+
+ IL.Emit(OpCodes.Ldarg_0);
+ IL.Emit(OpCodes.Call, defaultConstructor);
+
+ // __interceptor = (IInterceptor)info.GetValue("__interceptor", typeof(IInterceptor));
+ IL.Emit(OpCodes.Ldarg_0);
+ IL.Emit(OpCodes.Ldarg_1);
+ IL.Emit(OpCodes.Ldstr, "__interceptor");
+ IL.Emit(OpCodes.Ldloc, interceptorType);
+ IL.Emit(OpCodes.Callvirt, getValue);
+ IL.Emit(OpCodes.Castclass, typeof (IInterceptor));
+ IL.Emit(OpCodes.Stfld, interceptorField);
+
+ IL.Emit(OpCodes.Ret);
+ }
+
+ private static void AddSerializationSupport(System.Type baseType, System.Type[] baseInterfaces, TypeBuilder typeBuilder, FieldInfo interceptorField, ConstructorBuilder defaultConstructor)
+ {
+ ConstructorInfo serializableConstructor = typeof(SerializableAttribute).GetConstructor(new System.Type[0]);
+ var customAttributeBuilder = new CustomAttributeBuilder(serializableConstructor, new object[0]);
+ typeBuilder.SetCustomAttribute(customAttributeBuilder);
+
+ DefineSerializationConstructor(typeBuilder, interceptorField, defaultConstructor);
+ ImplementGetObjectData(baseType, baseInterfaces, typeBuilder, interceptorField);
+ }
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyImplementor.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyImplementor.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyImplementor.cs 2011-03-20 17:03:52 UTC (rev 5476)
@@ -0,0 +1,64 @@
+#region Credits
+
+// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project.
+// The license is the same of NHibernate license (LGPL Version 2.1, February 1999).
+// The source was then modified to be the default DynamicProxy of NHibernate project.
+
+#endregion
+
+using System;
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace NHibernate.Proxy.DynamicProxy
+{
+ internal class ProxyImplementor
+ {
+ private const MethodAttributes InterceptorMethodsAttributes = MethodAttributes.Public | MethodAttributes.HideBySig |
+ MethodAttributes.SpecialName | MethodAttributes.NewSlot |
+ MethodAttributes.Virtual;
+
+ private FieldBuilder field;
+
+ public FieldBuilder InterceptorField
+ {
+ get { return field; }
+ }
+
+ public void ImplementProxy(TypeBuilder typeBuilder)
+ {
+ // Implement the IProxy interface
+ typeBuilder.AddInterfaceImplementation(typeof (IProxy));
+
+ field = typeBuilder.DefineField("__interceptor", typeof (IInterceptor), FieldAttributes.Private);
+
+ // Implement the getter
+ MethodBuilder getterMethod = typeBuilder.DefineMethod("get_Interceptor", InterceptorMethodsAttributes, CallingConventions.HasThis, typeof(IInterceptor), new System.Type[0]);
+ getterMethod.SetImplementationFlags(MethodImplAttributes.Managed | MethodImplAttributes.IL);
+
+ ILGenerator IL = getterMethod.GetILGenerator();
+
+ // This is equivalent to:
+ // get { return __interceptor;
+ IL.Emit(OpCodes.Ldarg_0);
+ IL.Emit(OpCodes.Ldfld, field);
+ IL.Emit(OpCodes.Ret);
+
+ // Implement the setter
+ MethodBuilder setterMethod = typeBuilder.DefineMethod("set_Interceptor", InterceptorMethodsAttributes, CallingConventions.HasThis, typeof (void), new[] {typeof (IInterceptor)});
+
+ setterMethod.SetImplementationFlags(MethodImplAttributes.Managed | MethodImplAttributes.IL);
+ IL = setterMethod.GetILGenerator();
+ IL.Emit(OpCodes.Ldarg_0);
+ IL.Emit(OpCodes.Ldarg_1);
+ IL.Emit(OpCodes.Stfld, field);
+ IL.Emit(OpCodes.Ret);
+
+ MethodInfo originalSetter = typeof (IProxy).GetMethod("set_Interceptor");
+ MethodInfo originalGetter = typeof (IProxy).GetMethod("get_Interceptor");
+
+ typeBuilder.DefineMethodOverride(setterMethod, originalSetter);
+ typeBuilder.DefineMethodOverride(getterMethod, originalGetter);
+ }
+ }
+}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyObjectReference.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyObjectReference.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Proxy/DynamicProxy/ProxyObjectReference.cs 2011-03-20 17:03:52 UTC (rev 5476)
@@ -0,0 +1,63 @@
+#region Credits
+
+// This work is based on LinFu.DynamicProxy framework (c) Philip Laureano who has donated it to NHibernate project.
+// The license is the same of NHibernate license (LGPL Version 2.1, February 1999).
+// The source was then modified to be the default DynamicProxy of NHibernate project.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.Serialization;
+
+namespace NHibernate.Proxy.DynamicProxy
+{
+ [Serializable]
+ public class ProxyObjectReference : IObjectReference, ISerializable
+ {
+ private readonly System.Type _baseType;
+ private readonly IProxy _proxy;
+
+ protected ProxyObjectReference(SerializationInfo info, StreamingContext context)
+ {
+ // Deserialize the base type using its assembly qualified name
+ string qualifiedName = info.GetString("__baseType");
+ _baseType = System.Type.GetType(qualifiedName, true, false);
+
+ // Rebuild the list of interfaces
+ var interfaceList = new List<System.Type>();
+ int interfaceCount = info.GetInt32("__baseInterfaceCount");
+ for (int i = 0; i < interfaceCount; i++)
+ {
+ string keyName = string.Format("__baseInterface{0}", i);
+ string currentQualifiedName = info.GetString(keyName);
+ System.Type interfaceType = System.Type.GetType(currentQualifiedName, true, false);
+
+ interfaceList.Add(interfaceType);
+ }
+
+ // Reconstruct the proxy
+ var factory = new ProxyFactory();
+ System.Type proxyType = factory.CreateProxyType(_baseType, interfaceList.ToArray());
+
+ // Initialize the proxy with the deserialized data
+ var args = new object[] {info, context};
+ _proxy = (IProxy) Activator.CreateInstance(proxyType, args);
+ }
+
+ #region IObjectReference Members
+
+ public object GetRealObject(StreamingContext context)
+ {
+ return _proxy;
+ }
+
+ #endregion
+
+ #region ISerializable Members
+
+ public void GetObjectData(SerializationInfo info, StreamingContext context) {}
+
+ #endregion
+ }
+}
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|