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. |