⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pocoentitytuplizer.cs

📁 NHibernate NET开发者所需的
💻 CS
字号:
using System;
using System.Reflection;
using Iesi.Collections.Generic;
using log4net;
using NHibernate.Bytecode;
using NHibernate.Classic;
using NHibernate.Engine;
using NHibernate.Intercept;
using NHibernate.Mapping;
using NHibernate.Properties;
using NHibernate.Proxy;
using NHibernate.Type;

namespace NHibernate.Tuple.Entity
{
	/// <summary> An <see cref="IEntityTuplizer"/> specific to the POCO entity mode. </summary>
	public class PocoEntityTuplizer : AbstractEntityTuplizer
	{
		private static readonly ILog log = LogManager.GetLogger(typeof(PocoEntityTuplizer));
		private readonly System.Type mappedClass;
		private readonly System.Type proxyInterface;
		private readonly bool islifecycleImplementor;
		private readonly bool isValidatableImplementor;
		private readonly HashedSet<string> lazyPropertyNames = new HashedSet<string>();
		private readonly IReflectionOptimizer optimizer;

		public PocoEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappedEntity)
			: base(entityMetamodel, mappedEntity)
		{
			mappedClass = mappedEntity.MappedClass;
			proxyInterface = mappedEntity.ProxyInterface;
			islifecycleImplementor = typeof(ILifecycle).IsAssignableFrom(mappedClass);
			isValidatableImplementor = typeof(IValidatable).IsAssignableFrom(mappedClass);

			foreach (Mapping.Property property in mappedEntity.PropertyClosureIterator)
			{
				if (property.IsLazy)
					lazyPropertyNames.Add(property.Name);
			}

			if (hasCustomAccessors || !Cfg.Environment.UseReflectionOptimizer)
			{
				optimizer = null;
			}
			else
			{
				optimizer = Cfg.Environment.BytecodeProvider.GetReflectionOptimizer(mappedClass, getters, setters);
			}
		}

		public override System.Type ConcreteProxyClass
		{
			get { return proxyInterface; }
		}

		public override bool IsInstrumented
		{
			get { return FieldInterceptionHelper.IsInstrumented(MappedClass); }
		}

		public override System.Type MappedClass
		{
			get { return mappedClass; }
		}

		protected internal override IGetter BuildPropertyGetter(Mapping.Property mappedProperty, PersistentClass mappedEntity)
		{
			return mappedProperty.GetGetter(mappedEntity.MappedClass);
		}

		protected internal override ISetter BuildPropertySetter(Mapping.Property mappedProperty, PersistentClass mappedEntity)
		{
			return mappedProperty.GetSetter(mappedEntity.MappedClass);
		}

		protected internal override IInstantiator BuildInstantiator(PersistentClass persistentClass)
		{
			if (optimizer == null)
			{
				return new PocoInstantiator(persistentClass, null);
			}
			else
			{
				return new PocoInstantiator(persistentClass, optimizer.InstantiationOptimizer);
			}
		}

		protected internal override IProxyFactory BuildProxyFactory(PersistentClass persistentClass, IGetter idGetter,
		                                                            ISetter idSetter)
		{
			bool needAccesorCheck = true; // NH specific (look the comment below)

			// determine the id getter and setter methods from the proxy interface (if any)
			// determine all interfaces needed by the resulting proxy
			HashedSet<System.Type> proxyInterfaces = new HashedSet<System.Type>();
			proxyInterfaces.Add(typeof(INHibernateProxy));

			System.Type _mappedClass = persistentClass.MappedClass;
			System.Type _proxyInterface = persistentClass.ProxyInterface;

			if (_proxyInterface != null && !_mappedClass.Equals(_proxyInterface))
			{
				if (!_proxyInterface.IsInterface)
				{
					throw new MappingException("proxy must be either an interface, or the class itself: " + EntityName);
				}
				needAccesorCheck = false; // NH (the proxy is an interface all properties can be overridden)
				proxyInterfaces.Add(_proxyInterface);
			}

			if (_mappedClass.IsInterface)
			{
				needAccesorCheck = false; // NH (the mapped class is an interface all properties can be overridden)
				proxyInterfaces.Add(_mappedClass);
			}

			foreach (Subclass subclass in persistentClass.SubclassIterator)
			{
				System.Type subclassProxy = subclass.ProxyInterface;
				System.Type subclassClass = subclass.MappedClass;
				if (subclassProxy != null && !subclassClass.Equals(subclassProxy))
				{
					if (!subclassProxy.IsInterface)
					{
						throw new MappingException("proxy must be either an interface, or the class itself: " + subclass.EntityName);
					}
					proxyInterfaces.Add(subclassProxy);
				}
			}

			/* 
			 * NH Different Implementation (for Error logging):
			 * - Check if the logger is enabled
			 * - Don't need nothing to check if the mapped-class or proxy is an interface
			 */
			if (log.IsErrorEnabled && needAccesorCheck)
			{
				LogPropertyAccessorsErrors(persistentClass);
			}
			/**********************************************************/

			MethodInfo idGetterMethod = idGetter == null ? null : idGetter.Method;
			MethodInfo idSetterMethod = idSetter == null ? null : idSetter.Method;

			MethodInfo proxyGetIdentifierMethod = idGetterMethod == null || _proxyInterface == null ? null : 
				idGetterMethod;
				// TODO H3.2 different behaviour  ReflectHelper.GetMethod(_proxyInterface, idGetterMethod);

			MethodInfo proxySetIdentifierMethod = idSetterMethod == null || _proxyInterface == null ? null : 
				idSetterMethod;
				// TODO H3.2 different behaviour ReflectHelper.GetMethod(_proxyInterface, idSetterMethod);

			IProxyFactory pf = BuildProxyFactoryInternal(persistentClass, idGetter, idSetter);
			try
			{
				pf.PostInstantiate(EntityName, _mappedClass, proxyInterfaces, proxyGetIdentifierMethod, proxySetIdentifierMethod,
				                   persistentClass.HasEmbeddedIdentifier ? (IAbstractComponentType) persistentClass.Identifier.Type: null);
			}
			catch (HibernateException he)
			{
				log.Warn("could not create proxy factory for:" + EntityName, he);
				pf = null;
			}
			return pf;
		}

		private static void LogPropertyAccessorsErrors(PersistentClass persistentClass)
		{
			// This method work when Environment.UseProxyValidator is off

			System.Type clazz = persistentClass.MappedClass;
			foreach (Mapping.Property property in persistentClass.PropertyIterator)
			{
				MethodInfo method = property.GetGetter(clazz).Method;
				// In NET if IsVirtual is false or IsFinal is true, then the method cannot be overridden.
				if (method != null && (!method.IsVirtual || method.IsFinal))
				{
					log.Error(
						string.Format("Getters of lazy classes cannot be final: {0}.{1}", persistentClass.MappedClass.FullName,
						              property.Name));
				}
				method = property.GetSetter(clazz).Method;
				if (method != null && (!method.IsVirtual || method.IsFinal))
				{
					log.Error(
						string.Format("Setters of lazy classes cannot be final: {0}.{1}", persistentClass.MappedClass.FullName,
						              property.Name));
				}
			}
		}

		protected virtual IProxyFactory BuildProxyFactoryInternal(PersistentClass @class, IGetter getter, ISetter setter)
		{
			return Cfg.Environment.BytecodeProvider.ProxyFactoryFactory.BuildProxyFactory();
		}

		public override void AfterInitialize(object entity, bool lazyPropertiesAreUnfetched, ISessionImplementor session)
		{
			if (IsInstrumented)
			{
				HashedSet<string> lazyProps = lazyPropertiesAreUnfetched && EntityMetamodel.HasLazyProperties ? lazyPropertyNames : null;
				//TODO: if we support multiple fetch groups, we would need
				//      to clone the set of lazy properties!
				FieldInterceptionHelper.InjectFieldInterceptor(entity, EntityName, lazyProps, session);
			}
		}

		public override object[] GetPropertyValues(object entity)
		{
			if (ShouldGetAllProperties(entity) && optimizer != null && optimizer.AccessOptimizer != null)
			{
				return GetPropertyValuesWithOptimizer(entity);
			}
			else
			{
				return base.GetPropertyValues(entity);
			}
		}

		private object[] GetPropertyValuesWithOptimizer(object entity)
		{
			return optimizer.AccessOptimizer.GetPropertyValues(entity);
		}

		public override object[] GetPropertyValuesToInsert(object entity, System.Collections.IDictionary mergeMap, ISessionImplementor session)
		{
			if (ShouldGetAllProperties(entity) && optimizer != null && optimizer.AccessOptimizer != null)
			{
				return GetPropertyValuesWithOptimizer(entity);
			}
			else
			{
				return base.GetPropertyValuesToInsert(entity, mergeMap, session);
			}
		}

		public override bool HasUninitializedLazyProperties(object entity)
		{
			if (EntityMetamodel.HasLazyProperties)
			{
				IFieldInterceptor callback = FieldInterceptionHelper.ExtractFieldInterceptor(entity);
				return callback != null && !callback.IsInitialized;
			}
			else
			{
				return false;
			}
		}

		public override bool IsLifecycleImplementor
		{
			get { return islifecycleImplementor; }
		}

		public override void SetPropertyValues(object entity, object[] values)
		{
			if (!EntityMetamodel.HasLazyProperties && optimizer != null && optimizer.AccessOptimizer != null)
			{
				SetPropertyValuesWithOptimizer(entity, values);
			}
			else
			{
				base.SetPropertyValues(entity, values);
			}
		}

		private void SetPropertyValuesWithOptimizer(object entity, object[] values)
		{
			try
			{
				optimizer.AccessOptimizer.SetPropertyValues(entity, values);
			}
			catch (InvalidCastException e)
			{
				throw new PropertyAccessException(e, "Invalid Cast (check your mapping for property type mismatches);", true,
				                                  entity.GetType());
			}
		}

		public override bool IsValidatableImplementor
		{
			get { return isValidatableImplementor; }
		}

		public override EntityMode EntityMode
		{
			get { return NHibernate.EntityMode.Poco; }
		}
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -