From: <aye...@us...> - 2010-01-24 16:47:04
|
Revision: 4923 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4923&view=rev Author: ayenderahien Date: 2010-01-24 16:46:51 +0000 (Sun, 24 Jan 2010) Log Message: ----------- Implementing lazy properties * Removing ignore from the lazy property fixture * Adding LazyFieldInterceptor impl for Castle. Adding IFieldInterceptorAccessor to allow setting the field interceptor Adding convenience methods to detect property invocations * Adding DefaultFieldInterceptor - since we don't need one tied to the actual field interception impl * Removing temporary #region * Detecting usage of non collection lazy properties in entity meta model and considering this for instrumented fields * Implementing FieldInterceptionHelper Delegating responsibility for detecting interception to the proxy factory * Adding support for detecting lazy properties in the mapping * Simplifying code * Removed overly complex code * Binding properties laziness * Adding the ability to create field interception proxy to proxy factories. * Will create field interception proxy when needed LazyPropertyFixture basic test now works * Fixing off by one error * Adding more tests to verify lazy properties actually work * Implementing empty impl of the new field interception capabilities to other proxy factories impl * Updating loaded sln projects Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Bytecode/IProxyFactoryFactory.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmAny.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmArray.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmBag.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmComponent.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmDynamicComponent.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmIdbag.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmKeyManyToOne.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmKeyProperty.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmList.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmManyToOne.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmMap.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmNestedCompositeElement.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmOneToOne.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmPrimitiveArray.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmProperty.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmSet.cs trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/IEntityPropertyMapping.cs trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs trunk/nhibernate/src/NHibernate/Intercept/FieldInterceptionHelper.cs trunk/nhibernate/src/NHibernate/Intercept/IFieldInterceptor.cs trunk/nhibernate/src/NHibernate/NHibernate.csproj trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs trunk/nhibernate/src/NHibernate/Proxy/AbstractProxyFactory.cs trunk/nhibernate/src/NHibernate/Proxy/IProxyFactory.cs trunk/nhibernate/src/NHibernate/Proxy/Map/MapProxyFactory.cs trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs trunk/nhibernate/src/NHibernate/Tuple/Entity/PocoEntityTuplizer.cs trunk/nhibernate/src/NHibernate/Tuple/PocoInstantiator.cs trunk/nhibernate/src/NHibernate/Util/ReflectHelper.cs trunk/nhibernate/src/NHibernate.ByteCode.Castle/NHibernate.ByteCode.Castle.csproj trunk/nhibernate/src/NHibernate.ByteCode.Castle/ProxyFactory.cs trunk/nhibernate/src/NHibernate.ByteCode.Castle/ProxyFactoryFactory.cs trunk/nhibernate/src/NHibernate.ByteCode.Castle.Tests/ProxyInterface/CustomProxyFixture.cs trunk/nhibernate/src/NHibernate.ByteCode.LinFu/ProxyFactoryFactory.cs trunk/nhibernate/src/NHibernate.ByteCode.Spring/ProxyFactoryFactory.cs trunk/nhibernate/src/NHibernate.Test/Bytecode/WrongProxyFactoryFactory.cs trunk/nhibernate/src/NHibernate.Test/LazyProperty/LazyPropertyFixture.cs trunk/nhibernate/src/NHibernate.Test/LazyProperty/Mappings.hbm.xml trunk/nhibernate/src/NHibernate.Test/NHSpecificTest/SetFixture.cs trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.build trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj trunk/nhibernate/src/NHibernate.sln Added Paths: ----------- trunk/nhibernate/src/NHibernate/Intercept/DefaultFieldInterceptor.cs trunk/nhibernate/src/NHibernate/Intercept/IFieldInterceptorAccessor.cs trunk/nhibernate/src/NHibernate.ByteCode.Castle/LazyFieldInterceptor.cs Modified: trunk/nhibernate/src/NHibernate/Bytecode/IProxyFactoryFactory.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Bytecode/IProxyFactoryFactory.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Bytecode/IProxyFactoryFactory.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -36,5 +36,7 @@ */ IProxyValidator ProxyValidator { get; } + + bool IsInstrumented(System.Type entityClass); } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmAny.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmAny.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmAny.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -22,6 +22,11 @@ get { return optimisticlock; } } + public bool IsLazyProperty + { + get { return lazy; } + } + #endregion #region Overrides of AbstractDecoratable Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmArray.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmArray.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmArray.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -16,6 +16,11 @@ get { return access; } } + public bool IsLazyProperty + { + get { return false; } + } + public bool OptimisticLock { get { return optimisticlock; } Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmBag.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmBag.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmBag.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -17,6 +17,11 @@ get { return access; } } + public bool IsLazyProperty + { + get { return false; } + } + public bool OptimisticLock { get { return optimisticlock; } Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmComponent.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmComponent.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmComponent.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -23,6 +23,11 @@ get { return node; } } + public bool IsLazyProperty + { + get { return lazy; } + } + public string Name { get { return name; } Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmDynamicComponent.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmDynamicComponent.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmDynamicComponent.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -18,6 +18,11 @@ get { return null; } } + public bool IsLazyProperty + { + get { return false; } + } + public string EmbeddedNode { get { return node; } Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmIdbag.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmIdbag.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmIdbag.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -16,6 +16,11 @@ get { return access; } } + public bool IsLazyProperty + { + get { return false; } + } + public bool OptimisticLock { get { return optimisticlock; } Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmKeyManyToOne.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmKeyManyToOne.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmKeyManyToOne.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -70,6 +70,11 @@ get { return name; } } + public bool IsLazyProperty + { + get { return false; } + } + public string Access { get { return access; } Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmKeyProperty.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmKeyProperty.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmKeyProperty.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -56,6 +56,11 @@ get { return name; } } + public bool IsLazyProperty + { + get { return false; } + } + public string Access { get { return access; } Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmList.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmList.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmList.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -21,6 +21,11 @@ get { return optimisticlock; } } + public bool IsLazyProperty + { + get { return false; } + } + #endregion #region Implementation of IReferencePropertyMapping Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmManyToOne.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmManyToOne.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmManyToOne.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -18,6 +18,11 @@ get { return access; } } + public bool IsLazyProperty + { + get { return false; } + } + public bool OptimisticLock { get { return optimisticlock; } Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmMap.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmMap.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmMap.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -16,6 +16,11 @@ get { return access; } } + public bool IsLazyProperty + { + get { return false; } + } + public bool OptimisticLock { get { return optimisticlock; } Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmNestedCompositeElement.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmNestedCompositeElement.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmNestedCompositeElement.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -56,5 +56,10 @@ } #endregion + + public bool IsLazyProperty + { + get { return false; } + } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmOneToOne.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmOneToOne.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmOneToOne.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -76,5 +76,10 @@ { get { return lazySpecified ? lazy : (HbmLaziness?)null; } } + + public bool IsLazyProperty + { + get { return Lazy == HbmLaziness.Proxy; } + } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmPrimitiveArray.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmPrimitiveArray.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmPrimitiveArray.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -21,6 +21,11 @@ get { return optimisticlock; } } + public bool IsLazyProperty + { + get { return false; } + } + #endregion #region Implementation of IReferencePropertyMapping Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmProperty.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmProperty.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmProperty.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -13,6 +13,11 @@ get { return name; } } + public bool IsLazyProperty + { + get { return lazy; } + } + public string Access { get { return access; } @@ -62,7 +67,7 @@ unique = unique, uniqueSpecified = true, uniquekey = uniquekey, - index = index + index = index, }; } } Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmSet.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmSet.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/HbmSet.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -22,6 +22,11 @@ get { return optimisticlock; } } + public bool IsLazyProperty + { + get { return false; } + } + #endregion #region Implementation of IReferencePropertyMapping Modified: trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/IEntityPropertyMapping.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/IEntityPropertyMapping.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/MappingSchema/IEntityPropertyMapping.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -5,5 +5,6 @@ string Name { get; } string Access { get; } bool OptimisticLock { get; } + bool IsLazyProperty { get; } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Cfg/XmlHbmBinding/PropertiesBinder.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -362,6 +362,7 @@ Name = propertyMapping.Name, PropertyAccessorName = propertyAccessorName, Value = value, + IsLazy = propertyMapping.IsLazyProperty, IsOptimisticLocked = propertyMapping.OptimisticLock, MetaAttributes = GetMetas(propertyMapping, inheritedMetas) }; Modified: trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Intercept/AbstractFieldInterceptor.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -7,6 +7,8 @@ [Serializable] public abstract class AbstractFieldInterceptor : IFieldInterceptor { + public static readonly object InvokeImplementation = new object(); + [NonSerialized] private ISessionImplementor session; private ISet<string> uninitializedFields; @@ -72,41 +74,34 @@ get { return initializing; } } - protected internal object Intercept(object target, string fieldName, object value) + public object Intercept(object target, string fieldName) { - if (initializing) + if (initializing || + uninitializedFields == null || + !uninitializedFields.Contains(fieldName)) + return InvokeImplementation; + + if (session == null) { - return value; + throw new LazyInitializationException("entity with lazy properties is not associated with a session"); } - - if (uninitializedFields != null && uninitializedFields.Contains(fieldName)) + if (!session.IsOpen || !session.IsConnected) { - if (session == null) - { - throw new LazyInitializationException("entity with lazy properties is not associated with a session"); - } - else if (!session.IsOpen || !session.IsConnected) - { - throw new LazyInitializationException("session is not connected"); - } + throw new LazyInitializationException("session is not connected"); + } - object result; - initializing = true; - try - { - result = ((ILazyPropertyInitializer)session.Factory.GetEntityPersister(entityName)).InitializeLazyProperty(fieldName, target, session); - } - finally - { - initializing = false; - } - uninitializedFields = null; //let's assume that there is only one lazy fetch group, for now! - return result; + object result; + initializing = true; + try + { + result = ((ILazyPropertyInitializer)session.Factory.GetEntityPersister(entityName)).InitializeLazyProperty(fieldName, target, session); } - else + finally { - return value; + initializing = false; } + uninitializedFields = null; //let's assume that there is only one lazy fetch group, for now! + return result; } } } Added: trunk/nhibernate/src/NHibernate/Intercept/DefaultFieldInterceptor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Intercept/DefaultFieldInterceptor.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Intercept/DefaultFieldInterceptor.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -0,0 +1,13 @@ +using Iesi.Collections.Generic; +using NHibernate.Engine; + +namespace NHibernate.Intercept +{ + public class DefaultFieldInterceptor : AbstractFieldInterceptor + { + public DefaultFieldInterceptor(ISessionImplementor session, ISet<string> uninitializedFields, string entityName) + : base(session, uninitializedFields, entityName) + { + } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Intercept/FieldInterceptionHelper.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Intercept/FieldInterceptionHelper.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Intercept/FieldInterceptionHelper.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -7,44 +7,44 @@ public static class FieldInterceptionHelper { // VERY IMPORTANT!!!! - This class needs to be free of any static references - // to any Castle classes. Otherwise, users will always need both + // to any Castle/Spring/LinFu classes. Otherwise, users will always need both // on their classpaths no matter which (if either) they use. // // Another option here would be to remove the Hibernate.isPropertyInitialized() // method and have the users go through the SessionFactory to get this information. - - + public static bool IsInstrumented(System.Type entityClass) { - // TODO : Here code - return false; + // NH Specific: + // unlike Hibernate, NHibernate assumes that any class is valid for interception + // because we don't try to handle field interception + return Cfg.Environment.BytecodeProvider.ProxyFactoryFactory.IsInstrumented(entityClass); } - + public static bool IsInstrumented(object entity) { - return entity != null && IsInstrumented(entity.GetType()); + return entity is IFieldInterceptorAccessor; } - + public static IFieldInterceptor ExtractFieldInterceptor(object entity) { - if (entity == null) - { - return null; - } - // TODO : Here code to extract the Field Interceptor - return null; + var fieldInterceptorAccessor = entity as IFieldInterceptorAccessor; + return fieldInterceptorAccessor == null ? null : fieldInterceptorAccessor.FieldInterceptor; } - + public static IFieldInterceptor InjectFieldInterceptor(object entity, string entityName, ISet<string> uninitializedFieldNames, ISessionImplementor session) { - if (entity != null) + var fieldInterceptorAccessor = entity as IFieldInterceptorAccessor; + if (fieldInterceptorAccessor != null) { - // TODO : Here code to inject the Field Interceptor + var fieldInterceptorImpl = new DefaultFieldInterceptor(session, uninitializedFieldNames, entityName); + fieldInterceptorAccessor.FieldInterceptor = fieldInterceptorImpl; + return fieldInterceptorImpl; } return null; } - - public static void ClearDirty(object entity) + + public static void ClearDirty(object entity) { IFieldInterceptor interceptor = ExtractFieldInterceptor(entity); if (interceptor != null) @@ -52,8 +52,8 @@ interceptor.ClearDirty(); } } - - public static void MarkDirty(object entity) + + public static void MarkDirty(object entity) { IFieldInterceptor interceptor = ExtractFieldInterceptor(entity); if (interceptor != null) Modified: trunk/nhibernate/src/NHibernate/Intercept/IFieldInterceptor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Intercept/IFieldInterceptor.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Intercept/IFieldInterceptor.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -26,5 +26,8 @@ /// <summary> Clear the internal dirty flag.</summary> void ClearDirty(); + + /// <summary> Intercept field set/get </summary> + object Intercept(object target, string fieldName); } } \ No newline at end of file Added: trunk/nhibernate/src/NHibernate/Intercept/IFieldInterceptorAccessor.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Intercept/IFieldInterceptorAccessor.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Intercept/IFieldInterceptorAccessor.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -0,0 +1,7 @@ +namespace NHibernate.Intercept +{ + public interface IFieldInterceptorAccessor + { + IFieldInterceptor FieldInterceptor { get; set; } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj =================================================================== --- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2010-01-24 16:46:51 UTC (rev 4923) @@ -640,6 +640,8 @@ <Compile Include="Hql\Ast\ANTLR\Tree\UpdateStatement.cs" /> <Compile Include="Hql\Ast\HqlTreeBuilder.cs" /> <Compile Include="Hql\Ast\HqlTreeNode.cs" /> + <Compile Include="Intercept\DefaultFieldInterceptor.cs" /> + <Compile Include="Intercept\IFieldInterceptorAccessor.cs" /> <Compile Include="IQueryExpression.cs" /> <Compile Include="IQueryOver.cs" /> <Compile Include="Criterion\QueryOver.cs" /> Modified: trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Persister/Entity/AbstractEntityPersister.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -1245,7 +1245,7 @@ // are shared PK one-to-one associations which are // handled differently in the Type#nullSafeGet code... ps = session.Batcher.PrepareCommand(CommandType.Text, lazySelect, IdentifierType.SqlTypes(Factory)); - IdentifierType.NullSafeSet(ps, id, 1, session); + IdentifierType.NullSafeSet(ps, id, 0, session); rs = session.Batcher.ExecuteReader(ps); rs.Read(); } Modified: trunk/nhibernate/src/NHibernate/Proxy/AbstractProxyFactory.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/AbstractProxyFactory.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Proxy/AbstractProxyFactory.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -1,3 +1,4 @@ +using System; using System.Reflection; using Iesi.Collections.Generic; using NHibernate.Engine; @@ -42,5 +43,10 @@ public abstract INHibernateProxy GetProxy(object id, ISessionImplementor session); + + public virtual object GetFieldInterceptionProxy() + { + throw new NotSupportedException(); + } } } \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Proxy/IProxyFactory.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/IProxyFactory.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Proxy/IProxyFactory.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -5,48 +5,50 @@ namespace NHibernate.Proxy { - /// <summary> Contract for run-time, proxy-based lazy initialization proxies. </summary> - public interface IProxyFactory - { - /// <summary> Called immediately after instantiation of this factory. </summary> - /// <param name="entityName"> - /// The name of the entity for which this factory should generate proxies. - /// </param> - /// <param name="persistentClass"> - /// The entity class for which to generate proxies; not always the same as the entityName. - /// </param> - /// <param name="interfaces"> - /// The interfaces to expose in the generated proxy; - /// <see cref="INHibernateProxy"/> is already included in this collection. - /// </param> - /// <param name="getIdentifierMethod"> - /// Reference to the identifier getter method; invocation on this method should not force initialization - /// </param> - /// <param name="setIdentifierMethod"> - /// Reference to the identifier setter method; invocation on this method should not force initialization - /// </param> - /// <param name="componentIdType"> - /// For composite identifier types, a reference to - /// the <see cref="ComponentType">type</see> of the identifier - /// property; again accessing the id should generally not cause - /// initialization - but need to bear in mind key-many-to-one - /// mappings. - /// </param> - /// <exception cref="HibernateException"> Indicates a problem completing post </exception> - /// <remarks> - /// Essentially equivalent to constructor injection, but contracted - /// here via interface. - /// </remarks> - void PostInstantiate(string entityName, System.Type persistentClass, ISet<System.Type> interfaces, - MethodInfo getIdentifierMethod, MethodInfo setIdentifierMethod, IAbstractComponentType componentIdType); + /// <summary> Contract for run-time, proxy-based lazy initialization proxies. </summary> + public interface IProxyFactory + { + /// <summary> Called immediately after instantiation of this factory. </summary> + /// <param name="entityName"> + /// The name of the entity for which this factory should generate proxies. + /// </param> + /// <param name="persistentClass"> + /// The entity class for which to generate proxies; not always the same as the entityName. + /// </param> + /// <param name="interfaces"> + /// The interfaces to expose in the generated proxy; + /// <see cref="INHibernateProxy"/> is already included in this collection. + /// </param> + /// <param name="getIdentifierMethod"> + /// Reference to the identifier getter method; invocation on this method should not force initialization + /// </param> + /// <param name="setIdentifierMethod"> + /// Reference to the identifier setter method; invocation on this method should not force initialization + /// </param> + /// <param name="componentIdType"> + /// For composite identifier types, a reference to + /// the <see cref="ComponentType">type</see> of the identifier + /// property; again accessing the id should generally not cause + /// initialization - but need to bear in mind key-many-to-one + /// mappings. + /// </param> + /// <exception cref="HibernateException"> Indicates a problem completing post </exception> + /// <remarks> + /// Essentially equivalent to constructor injection, but contracted + /// here via interface. + /// </remarks> + void PostInstantiate(string entityName, System.Type persistentClass, ISet<System.Type> interfaces, + MethodInfo getIdentifierMethod, MethodInfo setIdentifierMethod, IAbstractComponentType componentIdType); - /// <summary> - /// Create a new proxy - /// </summary> - /// <param name="id">The id value for the proxy to be generated.</param> - /// <param name="session">The session to which the generated proxy will be associated.</param> - /// <returns>The generated proxy.</returns> - /// <exception cref="HibernateException">Indicates problems generating requested proxy.</exception> - INHibernateProxy GetProxy(object id, ISessionImplementor session); - } + /// <summary> + /// Create a new proxy + /// </summary> + /// <param name="id">The id value for the proxy to be generated.</param> + /// <param name="session">The session to which the generated proxy will be associated.</param> + /// <returns>The generated proxy.</returns> + /// <exception cref="HibernateException">Indicates problems generating requested proxy.</exception> + INHibernateProxy GetProxy(object id, ISessionImplementor session); + + object GetFieldInterceptionProxy(); + } } Modified: trunk/nhibernate/src/NHibernate/Proxy/Map/MapProxyFactory.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Proxy/Map/MapProxyFactory.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Proxy/Map/MapProxyFactory.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -1,3 +1,4 @@ +using System; using System.Reflection; using Iesi.Collections.Generic; using NHibernate.Engine; @@ -23,6 +24,11 @@ return new MapProxy(new MapLazyInitializer(entityName, id, session)); } + public object GetFieldInterceptionProxy() + { + throw new NotSupportedException(); + } + #endregion } } Modified: trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Tuple/Entity/EntityMetamodel.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -35,8 +35,6 @@ private readonly StandardProperty[] properties; - #region temporary - private readonly string[] propertyNames; private readonly IType[] propertyTypes; private readonly bool[] propertyLaziness; @@ -50,13 +48,12 @@ private readonly bool[] propertyVersionability; private readonly CascadeStyle[] cascadeStyles; - #endregion - private readonly IDictionary<string, int?> propertyIndexes = new Dictionary<string, int?>(); private readonly bool hasCollections; private readonly bool hasMutableProperties; private readonly bool hasLazyProperties; + private readonly int[] naturalIdPropertyNumbers; private bool lazy; @@ -106,8 +103,6 @@ properties = new StandardProperty[propertySpan]; List<int> naturalIdNumbers = new List<int>(); - #region temporary - propertyNames = new string[propertySpan]; propertyTypes = new IType[propertySpan]; propertyUpdateability = new bool[propertySpan]; @@ -121,9 +116,6 @@ propertyLaziness = new bool[propertySpan]; cascadeStyles = new CascadeStyle[propertySpan]; - #endregion - - int i = 0; int tempVersionProperty = NoVersionIndex; bool foundCascade = false; @@ -155,11 +147,11 @@ foundNonIdentifierPropertyNamedId = true; } - #region temporary - bool lazyProperty = prop.IsLazy && lazyAvailable; if (lazyProperty) + { hasLazy = true; + } propertyLaziness[i] = lazyProperty; propertyNames[i] = properties[i].Name; @@ -178,8 +170,6 @@ cascadeStyles[i] = properties[i].CascadeStyle; - #endregion - if (properties[i].IsLazy) { hasLazy = true; @@ -226,10 +216,22 @@ versionPropertyIndex = tempVersionProperty; hasLazyProperties = hasLazy; - if (hasLazyProperties) log.Info("lazy property fetching available for: " + name); - lazy = persistentClass.IsLazy && (!persistentClass.HasPocoRepresentation || !ReflectHelper.IsFinalClass(persistentClass.ProxyInterface)); + + if (hasLazy) + { + if (lazy == false) + { + log.WarnFormat("Disabled lazy properies fetching for {0} beacuse it does not support lazy at the entity level", name); + hasLazyProperties = false; + } + else + { + log.Info("lazy property fetching available for: " + name); + } + } + mutable = persistentClass.IsMutable; if (!persistentClass.IsAbstract.HasValue) Modified: trunk/nhibernate/src/NHibernate/Tuple/Entity/PocoEntityTuplizer.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Tuple/Entity/PocoEntityTuplizer.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Tuple/Entity/PocoEntityTuplizer.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -74,7 +74,11 @@ public override bool IsInstrumented { - get { return FieldInterceptionHelper.IsInstrumented(MappedClass); } + get { + return + EntityMetamodel.HasLazyProperties && + FieldInterceptionHelper.IsInstrumented(MappedClass); + } } public override System.Type MappedClass @@ -97,12 +101,12 @@ if (optimizer == null) { log.Debug("Create Instantiator without optimizer for:" + persistentClass.MappedClass.FullName); - return new PocoInstantiator(persistentClass, null); + return new PocoInstantiator(persistentClass, null, ProxyFactory, EntityMetamodel.HasLazyProperties); } else { log.Debug("Create Instantiator using optimizer for:" + persistentClass.MappedClass.FullName); - return new PocoInstantiator(persistentClass, optimizer.InstantiationOptimizer); + return new PocoInstantiator(persistentClass, optimizer.InstantiationOptimizer, ProxyFactory, EntityMetamodel.HasLazyProperties); } } Modified: trunk/nhibernate/src/NHibernate/Tuple/PocoInstantiator.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Tuple/PocoInstantiator.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Tuple/PocoInstantiator.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -4,6 +4,7 @@ using log4net; using NHibernate.Bytecode; using NHibernate.Mapping; +using NHibernate.Proxy; using NHibernate.Util; namespace NHibernate.Tuple @@ -19,6 +20,10 @@ [NonSerialized] private readonly IInstantiationOptimizer optimizer; + private readonly IProxyFactory proxyFactory; + + private readonly bool hasLazyProperties; + private readonly bool embeddedIdentifier; [NonSerialized] @@ -49,12 +54,14 @@ } } - public PocoInstantiator(PersistentClass persistentClass, IInstantiationOptimizer optimizer) + public PocoInstantiator(PersistentClass persistentClass, IInstantiationOptimizer optimizer, IProxyFactory proxyFactory, bool hasLazyProperties) { mappedClass = persistentClass.MappedClass; proxyInterface = persistentClass.ProxyInterface; embeddedIdentifier = persistentClass.HasEmbeddedIdentifier; this.optimizer = optimizer; + this.proxyFactory = proxyFactory; + this.hasLazyProperties = hasLazyProperties; try { @@ -81,29 +88,30 @@ { throw new InstantiationException("Cannot instantiate abstract class or interface: ", mappedClass); } - else if (optimizer != null) + if (hasLazyProperties) { + return proxyFactory.GetFieldInterceptionProxy(); + } + if (optimizer != null) + { return optimizer.CreateInstance(); } - else if (mappedClass.IsValueType) + if (mappedClass.IsValueType) { return Cfg.Environment.BytecodeProvider.ObjectsFactory.CreateInstance(mappedClass, true); } - else if (constructor == null) + if (constructor == null) { throw new InstantiationException("No default constructor for entity: ", mappedClass); } - else + try { - try - { - return constructor.Invoke(null); - } - catch (Exception e) - { - throw new InstantiationException("Could not instantiate entity: ", e, mappedClass); - } + return constructor.Invoke(null); } + catch (Exception e) + { + throw new InstantiationException("Could not instantiate entity: ", e, mappedClass); + } } public bool IsInstance(object obj) Modified: trunk/nhibernate/src/NHibernate/Util/ReflectHelper.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Util/ReflectHelper.cs 2010-01-22 14:04:02 UTC (rev 4922) +++ trunk/nhibernate/src/NHibernate/Util/ReflectHelper.cs 2010-01-24 16:46:51 UTC (rev 4923) @@ -9,613 +9,628 @@ namespace NHibernate.Util { - /// <summary> - /// Helper class for Reflection related code. - /// </summary> - public static class ReflectHelper - { - private static readonly ILog log = LogManager.GetLogger(typeof(ReflectHelper)); + /// <summary> + /// Helper class for Reflection related code. + /// </summary> + public static class ReflectHelper + { + private static readonly ILog log = LogManager.GetLogger(typeof(ReflectHelper)); - public const BindingFlags AnyVisibilityInstance = BindingFlags.Instance | BindingFlags.Public | - BindingFlags.NonPublic; + public const BindingFlags AnyVisibilityInstance = BindingFlags.Instance | BindingFlags.Public | + BindingFlags.NonPublic; - private static readonly System.Type[] NoClasses = System.Type.EmptyTypes; + private static readonly System.Type[] NoClasses = System.Type.EmptyTypes; - private static readonly MethodInfo Exception_InternalPreserveStackTrace = - typeof(Exception).GetMethod("InternalPreserveStackTrace", BindingFlags.Instance | BindingFlags.NonPublic); + private static readonly MethodInfo Exception_InternalPreserveStackTrace = + typeof(Exception).GetMethod("InternalPreserveStackTrace", BindingFlags.Instance | BindingFlags.NonPublic); - /// <summary> - /// Determine if the specified <see cref="System.Type"/> overrides the - /// implementation of Equals from <see cref="Object"/> - /// </summary> - /// <param name="clazz">The <see cref="System.Type"/> to reflect.</param> - /// <returns><see langword="true" /> if any type in the hierarchy overrides Equals(object).</returns> - public static bool OverridesEquals(System.Type clazz) - { - return OverrideMethod(clazz, "Equals", new[] { typeof(object) }); - } + /// <summary> + /// Determine if the specified <see cref="System.Type"/> overrides the + /// implementation of Equals from <see cref="Object"/> + /// </summary> + /// <param name="clazz">The <see cref="System.Type"/> to reflect.</param> + /// <returns><see langword="true" /> if any type in the hierarchy overrides Equals(object).</returns> + public static bool OverridesEquals(System.Type clazz) + { + return OverrideMethod(clazz, "Equals", new[] { typeof(object) }); + } - private static bool OverrideMethod(System.Type clazz, string methodName, System.Type[] parametersTypes) - { - try - { - MethodInfo method = !clazz.IsInterface - ? clazz.GetMethod(methodName, parametersTypes) - : GetMethodFromInterface(clazz, methodName, parametersTypes); - if (method == null) - { - return false; - } - else - { - // make sure that the DeclaringType is not System.Object - if that is the - // declaring type then there is no override. - return !method.DeclaringType.Equals(typeof(object)); - } - } - catch (AmbiguousMatchException) - { - // an ambigious match means that there is an override and it - // can't determine which one to use. - return true; - } - } + private static bool OverrideMethod(System.Type clazz, string methodName, System.Type[] parametersTypes) + { + try + { + MethodInfo method = !clazz.IsInterface + ? clazz.GetMethod(methodName, parametersTypes) + : GetMethodFromInterface(clazz, methodName, parametersTypes); + if (method == null) + { + return false; + } + else + { + // make sure that the DeclaringType is not System.Object - if that is the + // declaring type then there is no override. + return !method.DeclaringType.Equals(typeof(object)); + } + } + catch (AmbiguousMatchException) + { + // an ambigious match means that there is an override and it + // can't determine which one to use. + return true; + } + } - private static MethodInfo GetMethodFromInterface(System.Type type, string methodName, System.Type[] parametersTypes) - { - const BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly; - if(type == null) - { - return null; - } - MethodInfo method = type.GetMethod(methodName, flags, null, parametersTypes, null); - if (method == null) - { - System.Type[] interfaces = type.GetInterfaces(); - foreach (var @interface in interfaces) - { - method = GetMethodFromInterface(@interface, methodName, parametersTypes); - if(method != null) - { - return method; - } - } - } - return method; - } + private static MethodInfo GetMethodFromInterface(System.Type type, string methodName, System.Type[] parametersTypes) + { + const BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly; + if (type == null) + { + return null; + } + MethodInfo method = type.GetMethod(methodName, flags, null, parametersTypes, null); + if (method == null) + { + System.Type[] interfaces = type.GetInterfaces(); + foreach (var @interface in interfaces) + { + method = GetMethodFromInterface(@interface, methodName, parametersTypes); + if (method != null) + { + return method; + } + } + } + return method; + } - /// <summary> - /// Determine if the specified <see cref="System.Type"/> overrides the - /// implementation of GetHashCode from <see cref="Object"/> - /// </summary> - /// <param name="clazz">The <see cref="System.Type"/> to reflect.</param> - /// <returns><see langword="true" /> if any type in the hierarchy overrides GetHashCode().</returns> - public static bool OverridesGetHashCode(System.Type clazz) - { - return OverrideMethod(clazz, "GetHashCode", System.Type.EmptyTypes); - } + /// <summary> + /// Determine if the specified <see cref="System.Type"/> overrides the + /// implementation of GetHashCode from <see cref="Object"/> + /// </summary> + /// <param name="clazz">The <see cref="System.Type"/> to reflect.</param> + /// <returns><see langword="true" /> if any type in the hierarchy overrides GetHashCode().</returns> + public static bool OverridesGetHashCode(System.Type clazz) + { + return OverrideMethod(clazz, "GetHashCode", System.Type.EmptyTypes); + } - /// <summary> - /// Finds the <see cref="IGetter"/> for the property in the <see cref="System.Type"/>. - /// </summary> - /// <param name="theClass">The <see cref="System.Type"/> to find the property in.</param> - /// <param name="propertyName">The name of the Property to find.</param> - /// <param name="propertyAccessorName">The name of the property access strategy.</param> - /// <returns>The <see cref="IGetter"/> to get the value of the Property.</returns> - /// <remarks> - /// This one takes a propertyAccessor name as we might know the correct strategy by now so we avoid Exceptions which are costly - /// </remarks> - public static IGetter GetGetter(System.Type theClass, string propertyName, string propertyAccessorName) - { - return PropertyAccessorFactory - .GetPropertyAccessor(propertyAccessorName) - .GetGetter(theClass, propertyName); - } + /// <summary> + /// Finds the <see cref="IGetter"/> for the property in the <see cref="System.Type"/>. + /// </summary> + /// <param name="theClass">The <see cref="System.Type"/> to find the property in.</param> + /// <param name="propertyName">The name of the Property to find.</param> + /// <param name="propertyAccessorName">The name of the property access strategy.</param> + /// <returns>The <see cref="IGetter"/> to get the value of the Property.</returns> + /// <remarks> + /// This one takes a propertyAccessor name as we might know the correct strategy by now so we avoid Exceptions which are costly + /// </remarks> + public static IGetter GetGetter(System.Type theClass, string propertyName, string propertyAccessorName) + { + return PropertyAccessorFactory + .GetPropertyAccessor(propertyAccessorName) + .GetGetter(theClass, propertyName); + } - /// <summary> - /// Get the NHibernate <see cref="IType" /> for the named property of the <see cref="System.Type"/>. - /// </summary> - /// <param name="theClass">The <see cref="System.Type"/> to find the Property in.</param> - /// <param name="name">The name of the property/field to find in the class.</param> - /// <param name="access">The name of the property accessor for the property.</param> - /// <returns> - /// The NHibernate <see cref="IType"/> for the named property. - /// </returns> - public static IType ReflectedPropertyType(System.Type theClass, string name, string access) - { - System.Type propertyClass = ReflectedPropertyClass(theClass, name, access); + /// <summary> + /// Get the NHibernate <see cref="IType" /> for the named property of the <see cref="System.Type"/>. + /// </summary> + /// <param name="theClass">The <see cref="System.Type"/> to find the Property in.</param> + /// <param name="name">The name of the property/field to find in the class.</param> + /// <param name="access">The name of the property accessor for the property.</param> + /// <returns> + /// The NHibernate <see cref="IType"/> for the named property. + /// </returns> + public static IType ReflectedPropertyType(System.Type theClass, string name, string access) + { + System.Type propertyClass = ReflectedPropertyClass(theClass, name, access); - System.Type heuristicClass = propertyClass; + System.Type heuristicClass = propertyClass; - if (propertyClass.IsGenericType - && propertyClass.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) - { - heuristicClass = propertyClass.GetGenericArguments()[0]; - } + if (propertyClass.IsGenericType + && propertyClass.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) + { + heuristicClass = propertyClass.GetGenericArguments()[0]; + } - return TypeFactory.HeuristicType(heuristicClass.AssemblyQualifiedName); - } + return TypeFactory.HeuristicType(heuristicClass.AssemblyQualifiedName); + } - /// <summary> - /// Get the <see cref="System.Type" /> for the named property of a type. - /// </summary> - /// <param name="theClass">The <see cref="System.Type"/> to find the property in.</param> - /// <param name="name">The name of the property/field to find in the class.</param> - /// <param name="access">The name of the property accessor for the property.</param> - /// <returns>The <see cref="System.Type" /> for the named property.</returns> - public static System.Type ReflectedPropertyClass(System.Type theClass, string name, string access) - { - return GetGetter(theClass, name, access).ReturnType; - } + /// <summary> + /// Get the <see cref="System.Type" /> for the named property of a type. + /// </summary> + /// <param name="theClass">The <see cref="System.Type"/> to find the property in.</param> + /// <param name="name">The name of the property/field to find in the class.</param> + /// <param name="access">The name of the property accessor for the property.</param> + /// <returns>The <see cref="System.Type" /> for the named property.</returns> + public static System.Type ReflectedPropertyClass(System.Type theClass, string name, string access) + { + return GetGetter(theClass, name, access).ReturnType; + } - /// <summary> - /// Get the <see cref="System.Type" /> for the named property of a type. - /// </summary> - /// <param name="className">The FullName to find the property in.</param> - /// <param name="name">The name of the property/field to find in the class.</param> - /// <param name="accessorName">The name of the property accessor for the property.</param> - /// <returns>The <see cref="System.Type" /> for the named property.</returns> - public static System.Type ReflectedPropertyClass(string className, string name, string accessorName) - { - try - { - System.Type clazz = ClassForName(className); - return GetGetter(clazz, name, accessorName).ReturnType; - } - catch (Exception cnfe) - { - throw new MappingException(string.Format("class {0} not found while looking for property: {1}", className, name), cnfe); - } - } + /// <summary> + /// Get the <see cref="System.Type" /> for the named property of a type. + /// </summary> + /// <param name="className">The FullName to find the property in.</param> + /// <param name="name">The name of the property/field to find in the class.</param> + /// <param name="accessorName">The name of the property accessor for the property.</param> + /// <returns>The <see cref="System.Type" /> for the named property.</returns> + public static System.Type ReflectedPropertyClass(string className, string name, string accessorName) + { + try + { + System.Type clazz = ClassForName(className); + return GetGetter(clazz, name, accessorName).ReturnType; + } + catch (Exception cnfe) + { + throw new MappingException(string.Format("class {0} not found while looking for property: {1}", className, name), cnfe); + } + } - /// <summary> - /// Returns a reference to the Type. - /// </summary> - /// <param name="name">The name of the class or a fully qualified name.</param> - /// <returns>The Type for the Class.</returns> - public static System.Type ClassForName(string name) - { - AssemblyQualifiedTypeName parsedName = TypeNameParser.Parse(name); - System.Type result = TypeFromAssembly(parsedName, true); - return result; - } + /// <summary> + /// Returns a reference to the Type. + /// </summary> + /// <param name="name">The name of the class or a fully qualified name.</param> + /// <returns>The Type for the Class.</returns> + public static System.Type ClassForName(string name) + { + AssemblyQualifiedTypeName parsedName = TypeNameParser.Parse(name); + System.Type result = TypeFromAssembly(parsedName, true); + return result; + } - /// <summary> - /// Load a System.Type given is't name. - /// </summary> - /// <param name="classFullName">The class FullName or AssemblyQualifiedName</param> - /// <returns>The System.Type</returns> - /// <remarks> - /// If the <paramref name="classFullName"/> don't represent an <see cref="System.Type.AssemblyQualifiedName"/> - /// the method try to find the System.Type scanning all Assemblies of the <see cref="AppDomain.CurrentDomain"/>. - /// </remarks> - /// <exception cref="TypeLoadException">If no System.Type was found for <paramref name="classFullName"/>.</exception> - public static System.Type ClassForFullName(string classFullName) - { - System.Type result = null; - AssemblyQualifiedTypeName parsedName = TypeNameParser.Parse(classFullName); - if (!string.IsNullOrEmpty(parsedName.Assembly)) - { - result = TypeFromAssembly(parsedName, false); - } - else - { - if (!string.IsNullOrEmpty(classFullName)) - { - Assembly[] ass = AppDomain.CurrentDomain.GetAssemblies(); - foreach (Assembly a in ass) - { - result = a.GetType(classFullName, false, false); - if (result != null) - break; //<<<<<================ - } - } - } - if (result == null) - { - string message = "Could not load type " + classFullName + ". Possible cause: the assembly was not loaded or not specified."; - throw new TypeLoadException(message); - } + /// <summary> + /// Load a System.Type given is't name. + /// </summary> + /// <param name="classFullName">The class FullName or AssemblyQualifiedName</param> + /// <returns>The System.Type</returns> + /// <remarks> + /// If the <paramref name="classFullName"/> don't represent an <see cref="System.Type.AssemblyQualifiedName"/> + /// the method try to find the System.Type scanning all Assemblies of the <see cref="AppDomain.CurrentDomain"/>. + /// </remarks> + /// <exception cref="TypeLoadException">If no System.Type was found for <paramref name="classFullName"/>.</exception> + public static System.Type ClassForFullName(string classFullName) + { + System.Type result = null; + AssemblyQualifiedTypeName parsedName = TypeNameParser.Parse(classFullName); + if (!string.IsNullOrEmpty(parsedName.Assembly)) + { + result = TypeFromAssembly(parsedName, false); + } + else + { + if (!string.IsNullOrEmpty(classFullName)) + { + Assembly[] ass = AppDomain.CurrentDomain.GetAssemblies(); + foreach (Assembly a in ass) + { + result = a.GetType(classFullName, false, false); + if (result != null) + break; //<<<<<================ + } + } + } + if (result == null) + { + string message = "Could not load type " + classFullName + ". Possible cause: the assembly was not loaded or not specified."; + throw new TypeLoadException(message); + } - return result; - } + return result; + } - public static System.Type TypeFromAssembly(string type, string assembly, bool throwIfError) - { - return TypeFromAssembly(new AssemblyQualifiedTypeName(type, assembly), throwIfError); - } + public static System.Type TypeFromAssembly(string type, string assembly, bool throwIfError) + { + return TypeFromAssembly(new AssemblyQualifiedTypeName(type, assembly), throwIfError); + } - /// <summary> - /// Returns a <see cref="System.Type"/> from an already loaded Assembly or an - /// Assembly that is loaded with a partial name. - /// </summary> - /// <param name="name">An <see cref="AssemblyQualifiedTypeName" />.</param> - /// <param name="throwOnError"><see langword="true" /> if an exception should be thrown - /// in case of an error, <see langword="false" /> otherwise.</param> - /// <returns> - /// A <see cref="System.Type"/> object that represents the specified type, - /// or <see langword="null" /> if the type cannot be loaded. - /// </returns> - /// <remarks> - /// Attempts to get a reference to the type from an already loaded assembly. If the - /// type cannot be found then the assembly is loaded using - /// <see cref="Assembly.Load(string)" />. - /// </remarks> - public static System.Type TypeFromAssembly(AssemblyQualifiedTypeName name, bool throwOnError) - { - try - { - // Try to get the type from an already loaded assembly - System.Type type = System.Type.GetType(name.ToString()); + /// <summary> + /// Returns a <see cref="System.Type"/> from an already loaded Assembly or an + /// Assembly that is loaded with a partial name. + /// </summary> + /// <param name="name">An <see cref="AssemblyQualifiedTypeName" />.</param> + /// <param name="throwOnError"><see langword="true" /> if an exception should be thrown + /// in case of an error, <see langword="false" /> otherwise.</param> + /// <returns> + /// A <see cref="System.Type"/> object that represents the specified type, + /// or <see langword="null" /> if the type cannot be loaded. + /// </returns> + /// <remarks> + /// Attempts to get a reference to the type from an already loaded assembly. If the + /// type cannot be found then the assembly is loaded using + /// <see cref="Assembly.Load(string)" />. + /// </remarks> + public static System.Type TypeFromAssembly(AssemblyQualifiedTypeName name, bool throwOnError) + { + try + { + // Try to get the type from an already loaded assembly + System.Type type = System.Type.GetType(name.ToString()); - if (type != null) - { - return type; - } + if (type != null) + { + return type; + } - if (name.Assembly == null) - { - // No assembly was specified for the type, so just fail - string message = "Could not load type " + name + ". Possible cause: no assembly name specified."; - log.Warn(message); - if (throwOnError) throw new TypeLoadException(message); - return null; - } + if (name.Assembly == null) + { + // No assembly was specified for the type, so just fail + string message = "Could not load type " + name + ". Possible cause: no assembly name specified."; + log.Warn(message); + if (throwOnError) throw new TypeLoadException(message); + return null; + } - Assembly assembly = Assembly.Load(name.Assembly); + Assembly assembly = Assembly.Load(name.Assembly); - if (assembly == null) - { - log.Warn("Could not load type " + name + ". Possible cause: incorrect assembly name specified."); - return null; - } + if (assembly == null) + { + log.Warn("Could not load type " + name + ". Possible cause: incorrect assembly name specified."); + return null; + } - type = assembly.GetType(name.Type, throwOnError); + type = assembly.GetType(name.Type, throwOnError); - if (type == null) - { - log.Warn("Could not load type " + name + "."); - return null; - } + if (type == null) + { + log.Warn("Could not load type " + name + "."); + return null; + } - return type; - } - catch (Exception e) - { - if (log.IsErrorEnabled) - { - log.Error("Could not load type " + name + ".", e); - } - if (throwOnError) throw; - return null; - } - } + return type; + } + catch (Exception e) + { + ... [truncated message content] |