From: Michael D. <mik...@us...> - 2004-11-11 22:35:38
|
Update of /cvsroot/nhibernate/nhibernate/src/NHibernate/Proxy In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv2187/src/NHibernate/Proxy Modified Files: Tag: alpha_avalon-proxy INHibernateProxy.cs IProxyGenerator.cs LazyInitializer.cs ProxyGeneratorFactory.cs Added Files: Tag: alpha_avalon-proxy CastleCustomProxyGenerator.cs CastleLazyInitializer.cs CastleProxyGenerator.cs Removed Files: Tag: alpha_avalon-proxy AvalonLazyInitializer.cs AvalonProxyDeserializer.cs AvalonProxyGenerator.cs Log Message: updated to latest version of DynamicProxy --- AvalonProxyGenerator.cs DELETED --- Index: IProxyGenerator.cs =================================================================== RCS file: /cvsroot/nhibernate/nhibernate/src/NHibernate/Proxy/Attic/IProxyGenerator.cs,v retrieving revision 1.1.2.3 retrieving revision 1.1.2.4 diff -C2 -d -r1.1.2.3 -r1.1.2.4 *** IProxyGenerator.cs 5 Oct 2004 15:25:05 -0000 1.1.2.3 --- IProxyGenerator.cs 11 Nov 2004 22:34:57 -0000 1.1.2.4 *************** *** 13,17 **** /// <summary> ! /// Build a proxy using the Apache.Avalon.DynamicProxy library. /// </summary> /// <param name="persistentClass">The PersistentClass to proxy.</param> --- 13,17 ---- /// <summary> ! /// Build a proxy using the Castle.DynamicProxy library. /// </summary> /// <param name="persistentClass">The PersistentClass to proxy.</param> Index: INHibernateProxy.cs =================================================================== RCS file: /cvsroot/nhibernate/nhibernate/src/NHibernate/Proxy/Attic/INHibernateProxy.cs,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -C2 -d -r1.1.2.1 -r1.1.2.2 *** INHibernateProxy.cs 27 Sep 2004 03:42:03 -0000 1.1.2.1 --- INHibernateProxy.cs 11 Nov 2004 22:34:57 -0000 1.1.2.2 *************** *** 6,11 **** /// <summary> /// A marker interface so NHibernate can know if it is dealing with ! /// an object that is a Proxy. All NHibernate Proxies will be Serializable. ! /// This does not mean that all Mapped Classes have to be Serializable. /// </summary> /// <remarks> --- 6,10 ---- /// <summary> /// A marker interface so NHibernate can know if it is dealing with ! /// an object that is a Proxy. /// </summary> /// <remarks> *************** *** 14,18 **** /// the Proxies are created in a seperate DLL than NHibernate. /// </remarks> ! public interface INHibernateProxy : ISerializable { } --- 13,17 ---- /// the Proxies are created in a seperate DLL than NHibernate. /// </remarks> ! public interface INHibernateProxy { } --- NEW FILE: CastleProxyGenerator.cs --- using System; using System.Collections; using System.Reflection; using System.Reflection.Emit; using Castle.DynamicProxy; using Castle.DynamicProxy.Builder; using Castle.DynamicProxy.Builder.CodeGenerators; using NHibernate.Engine; namespace NHibernate.Proxy { /// <summary> /// An <see cref="IProxyGenerator"/> that uses the Castle.DynamicProxy library. /// </summary> public class CastleProxyGenerator : IProxyGenerator { private static readonly log4net.ILog log = log4net.LogManager.GetLogger( typeof(CastleProxyGenerator) ); // key = mapped type // value = proxy type private IDictionary cachedProxyTypes; private GeneratorContext _context; private ModuleScope _scope; /// <summary> /// Initializes a new instance of the <see cref="CastleProxyGenerator"/> class. /// </summary> internal CastleProxyGenerator() { cachedProxyTypes = new Hashtable(); _scope = new ModuleScope(); // the EnhanceTypeDelegate will add custom code gen that DynamicProxy does not provide // by default. _context = new GeneratorContext( );// new EnhanceTypeDelegate( EnhanceInterfaceType ), null ); } /// <summary> /// Marks the Proxy with the <see cref="SerializableAttribute"/>. /// </summary> /// <param name="mainType"></param> /// <param name="handlerFieldBuilder"></param> /// <param name="constructorBuilder"></param> /// <remarks> /// The proxy itself is not really serializable, it is replaced with a different object during /// serialization. This object knows how to recreate the proxy during the deserialization /// process. /// </remarks> private void EnhanceInterfaceType(TypeBuilder mainType, FieldBuilder handlerFieldBuilder, ConstructorBuilder constructorBuilder) { bool isSerializableAttFound = false; System.Type baseType = mainType.BaseType; // I don't know why I can't find the [Serializable] on the generated type if( isSerializableAttFound==false ) { ConstructorInfo serAttConstructor = typeof(SerializableAttribute).GetConstructor( new System.Type[0] ); CustomAttributeBuilder serializableAttBuilder = new CustomAttributeBuilder( serAttConstructor, new object[0] ); mainType.SetCustomAttribute( serializableAttBuilder ); } } #region IProxyGenerator Methods /// <summary> /// Build a proxy using the Castle.DynamicProxy library. /// </summary> /// <param name="persistentClass">.</param> /// <param name="interfaces">The extra interfaces the Proxy should implement.</param> /// <param name="identifierPropertyInfo">The PropertyInfo to get/set the Id.</param> /// <param name="id">The value for the Id.</param> /// <param name="session">The Session the proxy is in.</param> /// <returns>A fully built <c>INHibernateProxy</c>.</returns> public INHibernateProxy GetProxy(System.Type persistentClass, System.Type concreteProxy, System.Type[] interfaces, PropertyInfo identifierPropertyInfo, object id, ISessionImplementor session) { object generatedProxy = null; try { CastleLazyInitializer initializer = new CastleLazyInitializer( persistentClass, concreteProxy, interfaces, id, identifierPropertyInfo, session ); System.Type proxyType = null; // if I try to generate a proxy twice for the same type the Castle library will do the same // in one ModuleBuilder. The ModuleBuilder throws an exception (not suprisingly) when you try // to define the same type twice in it. So nh needs to keep a cache of the proxy types that have // already been generated. lock( cachedProxyTypes.SyncRoot ) { proxyType = cachedProxyTypes[ concreteProxy ] as System.Type; // if the pc is an interface then we need to add the interface to the // interfaces array that was passed in because it only includes the extra // interfaces for that persistent class. //if( persistentClass.IsInterface ) if( concreteProxy.IsInterface ) { if( proxyType==null ) { //TODO: figure out if this is necessary because the concreteProxy is // already included in the interfaces array... System.Type[] temp = new System.Type[ interfaces.Length + 1 ]; interfaces.CopyTo( temp, 0 ); temp[ interfaces.Length ] = concreteProxy; //persistentClass; interfaces = temp; InterfaceProxyGenerator _interfaceGenerator = new InterfaceProxyGenerator( _scope, _context ); proxyType = _interfaceGenerator.GenerateCode( interfaces ); cachedProxyTypes[ concreteProxy ] = proxyType; } // don't understand why a Interface proxy requires 2 arg constructor and a Class Interface // proxy only requires 1 - TODO: email Hammett about this. // hack with new object() because an interface proxy is expecting an actual target instance - we // don't have that yet and don't want to create it until it is actually needed. generatedProxy = Activator.CreateInstance( proxyType, new object[] { initializer, new object() } ); } else { if( proxyType==null ) { CastleCustomProxyGenerator _classGenerator = new CastleCustomProxyGenerator( _scope, _context ); proxyType = _classGenerator.GenerateCode( concreteProxy ); cachedProxyTypes[ concreteProxy ] = proxyType; } generatedProxy = Activator.CreateInstance( proxyType, new object[] { initializer } ); } } //object generatedProxy = Activator.CreateInstance( proxyType, new object[] { initializer } ); return (INHibernateProxy)generatedProxy; } catch(Exception e) { log.Error("Castle Dynamic Class Generator failed", e); throw new HibernateException( "Castle Dynamic Class Generator failed", e); } } /// <summary> /// Gets the <see cref="LazyInitializer"/> that is used by the Proxy. /// </summary> /// <param name="proxy">The Proxy object</param> /// <returns>The <see cref="LazyInitializer"/> that contains the details of the Proxied object.</returns> public LazyInitializer GetLazyInitializer(INHibernateProxy proxy) { // have to hard code in "__interceptor" - very dependant on them not changing their // implementation - email Hammet about this - or atleast to provide a static // field object fieldValue = proxy.GetType().GetField( "__interceptor" ).GetValue( proxy ); return (LazyInitializer)fieldValue; } /// <summary> /// Convenience method to figure out the underlying type for the object regardless of it /// is a Proxied object or the real object. /// </summary> /// <param name="obj">The object to get the type of.</param> /// <returns>The Underlying Type for the object regardless of if it is a Proxy.</returns> public System.Type GetClass(object obj) { if (obj is INHibernateProxy) { INHibernateProxy proxy = (INHibernateProxy) obj; LazyInitializer li = GetLazyInitializer( proxy ); return li.PersistentClass; } else { return obj.GetType(); } } #endregion } } --- NEW FILE: CastleCustomProxyGenerator.cs --- using System; using System.Reflection.Emit; using Castle.DynamicProxy; using Castle.DynamicProxy.Builder.CodeBuilder; using Castle.DynamicProxy.Builder.CodeGenerators; namespace NHibernate.Proxy { /// <summary> /// This will build a proxy for a <see cref="System.Type"/> that is /// a <c>Class</c> and then add the <see cref="INHibernateProxy"/> /// interface to it. /// </summary> public class CastleCustomProxyGenerator : ClassProxyGenerator { public CastleCustomProxyGenerator(ModuleScope scope) : base(scope) { } public CastleCustomProxyGenerator(ModuleScope scope, GeneratorContext context) : base(scope, context) { } /// <summary> /// Override of the <see cref="BasicCodeGenerator.CreateTypeBuilder(System.Type, System.Type[])"/> implementation. /// </summary> /// <param name="baseType">The base <see cref="System.Type"/> for the Proxy.</param> /// <param name="interfaces">The extra <see cref="System.Type"/> interfaces for the Proxy to implement.</param> /// <returns>An <see cref="EasyType"/> with the required interfaces added.</returns> protected override EasyType CreateTypeBuilder(System.Type baseType, System.Type[] interfaces) { bool isImplemented = false; // check to see if this implements INHibernateProxy - if not then make it // implement the interface for( int i=0; i<interfaces.Length; i++) { if( interfaces[i].Equals( typeof(INHibernateProxy) ) ) { isImplemented = true; } } if( isImplemented==false ) { int length = interfaces.Length; System.Type[] newInterfaces = new System.Type[ length + 1 ]; Array.Copy( interfaces, 0, newInterfaces, 0, length ); newInterfaces[ length ] = typeof(INHibernateProxy); interfaces = newInterfaces; } return base.CreateTypeBuilder(baseType, interfaces); } } } Index: LazyInitializer.cs =================================================================== RCS file: /cvsroot/nhibernate/nhibernate/src/NHibernate/Proxy/LazyInitializer.cs,v retrieving revision 1.1.2.5 retrieving revision 1.1.2.6 diff -C2 -d -r1.1.2.5 -r1.1.2.6 *** LazyInitializer.cs 5 Oct 2004 15:34:49 -0000 1.1.2.5 --- LazyInitializer.cs 11 Nov 2004 22:34:57 -0000 1.1.2.6 *************** *** 18,21 **** --- 18,22 ---- /// to cglib was made in .net. /// </remarks> + [Serializable] public abstract class LazyInitializer { *************** *** 28,31 **** --- 29,33 ---- protected object _target = null; protected object _id; + [NonSerialized] protected ISessionImplementor _session; protected System.Type _persistentClass; *************** *** 104,108 **** /// </summary> /// <param name="info">The <see cref="SerializationInfo"/> to write the object to.</param> ! protected abstract void AddSerializationInfo(SerializationInfo info); public object Identifier --- 106,112 ---- /// </summary> /// <param name="info">The <see cref="SerializationInfo"/> to write the object to.</param> ! protected virtual void AddSerializationInfo(SerializationInfo info) ! { ! } public object Identifier *************** *** 176,179 **** --- 180,186 ---- { // all Proxies must implement INHibernateProxy which extends ISerializable + // not true anymore - DynamicProxy now handles the serialization. All Proxy + // Generators should make sure that ISerializable is implemented if their + // Proxy doesn't do it by default. if( method.Name.Equals("GetObjectData") ) { --- AvalonLazyInitializer.cs DELETED --- --- AvalonProxyDeserializer.cs DELETED --- Index: ProxyGeneratorFactory.cs =================================================================== RCS file: /cvsroot/nhibernate/nhibernate/src/NHibernate/Proxy/Attic/ProxyGeneratorFactory.cs,v retrieving revision 1.1.2.3 retrieving revision 1.1.2.4 diff -C2 -d -r1.1.2.3 -r1.1.2.4 *** ProxyGeneratorFactory.cs 5 Oct 2004 15:25:05 -0000 1.1.2.3 --- ProxyGeneratorFactory.cs 11 Nov 2004 22:34:57 -0000 1.1.2.4 *************** *** 2,6 **** using System.Reflection; ! using Apache.Avalon.DynamicProxy; using NHibernate.Engine; --- 2,6 ---- using System.Reflection; ! using Castle.DynamicProxy; using NHibernate.Engine; *************** *** 15,19 **** private static readonly log4net.ILog log = log4net.LogManager.GetLogger( typeof(ProxyGeneratorFactory) ); ! private static IProxyGenerator _generator = new AvalonProxyGenerator(); public static IProxyGenerator GetProxyGenerator() --- 15,19 ---- private static readonly log4net.ILog log = log4net.LogManager.GetLogger( typeof(ProxyGeneratorFactory) ); ! private static IProxyGenerator _generator = new CastleProxyGenerator(); public static IProxyGenerator GetProxyGenerator() --- NEW FILE: CastleLazyInitializer.cs --- using System; using System.Collections; using System.Reflection; using System.Runtime.Serialization; using Castle.DynamicProxy; using NHibernate.Engine; namespace NHibernate.Proxy { /// <summary> /// A <see cref="LazyInitiliazer"/> for use with the Castle Dynamic Class Generator. /// </summary> [Serializable] public class CastleLazyInitializer : LazyInitializer, Castle.DynamicProxy.IInterceptor//, ISerializable { private static readonly log4net.ILog log = log4net.LogManager.GetLogger( typeof(CastleLazyInitializer) ); private System.Type _concreteProxy; private System.Type[] _interfaces; /// <summary> /// Initializes a new <see cref="CastleLazyInitializer"/> object. /// </summary> /// <param name="persistentClass">The Class to Proxy.</param> /// <param name="concreteProxy">The <see cref="System.Type"/> to use as the Proxy.</param> /// <param name="interfaces">An array of <see cref="System.Type"/> interfaces that the Proxy should implement.</param> /// <param name="id">The Id of the Object we are Proxying.</param> /// <param name="identifierPropertyInfo">The PropertyInfo for the <id> property.</param> /// <param name="session">The ISession this Proxy is in.</param> internal CastleLazyInitializer(System.Type persistentClass, System.Type concreteProxy, System.Type[] interfaces, object id, PropertyInfo identifierPropertyInfo, ISessionImplementor session) : base (persistentClass, id, identifierPropertyInfo, session) { _concreteProxy = concreteProxy; _interfaces = interfaces; } #region Castle.DynamicProxy.IInterceptor Members /// <summary> /// Invoke the actual Property/Method using the Proxy or instantiate the actual /// object and use it when the Proxy can't handle the method. /// </summary> /// <param name="invocation">The <see cref="IInvocation"/> from the generated Castle.DynamicProxy.</param> /// <param name="args">The parameters for the Method/Property</param> /// <returns>The result just like the actual object was called.</returns> public object Intercept(IInvocation invocation, params object[] args) { // let the generic LazyInitializer figure out if this can be handled // with the proxy or if the real class needs to be initialized object result = base.Invoke( invocation.Method, args); // the base LazyInitializer could not handle it so we need to Invoke // the method/property against the real class if( result==InvokeImplementation ) { invocation.InvocationTarget = GetImplementation(); return invocation.Proceed( args ); //return invocation.Method.Invoke( GetImplementation(), args ); } else { return result; } } #endregion } } |