Ok, below is what I have at the moment and it is working. What I want is to
be able to override the default tuplizer with a customized version that does
exactly everything that the existing tuplizer does, but rather than looking
for the default no-args constructor I want it to first check to see whether
my IoC container can provide the instance. It feels a little awkward to have
to change the IInstantiator AND the ITuplizer, to me it makes sense that the
IInstantiator should be responsible for making decisions on whether or not a
no-args constructor should be available. But at the moment that check is
spread out across both classes. Does it sound sensible to change that?

I have had to basically copy the code from PocoEntityTuplizer verbatim,
because I don't know enough about the nh internals to know whether I need
the code that relates to optimizers, instrumented fields, etc:

    public class IocProxyFactoryFactory : IProxyFactoryFactory
    {
        public IProxyFactory BuildProxyFactory()
        {
            return new ProxyFactory();
        }

        public IProxyValidator ProxyValidator
        {
            get { return new IocDynProxyTypeValidator(); }
        }
    }

    public class IocDynProxyTypeValidator : DynProxyTypeValidator
    {
        protected override void CheckHasVisibleDefaultConstructor(Type type)
        {
            if (IoC.IsInitialized &&
!IoC.Container.Kernel.HasComponent(type))
                base.CheckHasVisibleDefaultConstructor(type);
        }
    }

    public class IocTuplizer : 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;
        private readonly IProxyValidator proxyValidator;

        public IocTuplizer(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 || (IoC.IsInitialized &&
IoC.Container.Kernel.HasComponent(mappedClass)))
            {
                optimizer = null;
            }
            else
            {
                optimizer =
Cfg.Environment.BytecodeProvider.GetReflectionOptimizer(mappedClass,
getters, setters);
            }

            proxyValidator =
Cfg.Environment.BytecodeProvider.ProxyFactoryFactory.ProxyValidator;
        }

        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 override IGetter BuildPropertyGetter(Property
mappedProperty, PersistentClass mappedEntity)
        {
            return mappedProperty.GetGetter(mappedEntity.MappedClass);
        }

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

        protected override IInstantiator BuildInstantiator(PersistentClass
persistentClass)
        {
            return new IocInstantiator(persistentClass, null);
        }

        protected 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
            var proxyInterfaces = new HashedSet<System.Type> {
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 :
                ReflectHelper.TryGetMethod(_proxyInterface, idGetterMethod);

            MethodInfo proxySetIdentifierMethod = idSetterMethod == null ||
_proxyInterface == null ? null :
                ReflectHelper.TryGetMethod(_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 void LogPropertyAccessorsErrors(PersistentClass
persistentClass)
        {
            if (proxyValidator == null)
            {
                return;
            }

            // 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;
                if (!proxyValidator.IsProxeable(method))
                {
                    log.Error(
                        string.Format("Getters of lazy classes cannot be
final: {0}.{1}", persistentClass.MappedClass.FullName,
                                      property.Name));
                }
                method = property.GetSetter(clazz).Method;
                if (!proxyValidator.IsProxeable(method))
                {
                    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 EntityMode.Poco; }
        }
    }

    [Serializable]
    public class IocInstantiator : IInstantiator, IDeserializationCallback
    {
        private static readonly ILog log =
LogManager.GetLogger(typeof(PocoInstantiator));

        [NonSerialized]
        private readonly IInstantiationOptimizer optimizer;
        private readonly bool embeddedIdentifier;
        private readonly Type mappedClass;
        private readonly Type proxyInterface;

        [NonSerialized]
        private ConstructorInfo constructor;

        public IocInstantiator()
        {
        }

        public IocInstantiator(Component component, IInstantiationOptimizer
optimizer)
        {
            mappedClass = component.ComponentClass;
            this.optimizer = optimizer;

            proxyInterface = null;
            embeddedIdentifier = false;

            if (IoC.IsInitialized &&
IoC.Container.Kernel.HasComponent(mappedClass))
                constructor = null;
            else
            {
                try
                {
                    constructor =
ReflectHelper.GetDefaultConstructor(mappedClass);
                }
                catch (PropertyNotFoundException)
                {
                    log.Info(string.Format("no default (no-argument)
constructor for class: {0} (class must be instantiated by Interceptor)",
mappedClass.FullName));
                    constructor = null;
                }
            }
        }

        public IocInstantiator(PersistentClass persistentClass,
IInstantiationOptimizer optimizer)
        {
            mappedClass = persistentClass.MappedClass;
            proxyInterface = persistentClass.ProxyInterface;
            embeddedIdentifier = persistentClass.HasEmbeddedIdentifier;
            this.optimizer = optimizer;

            if (IoC.IsInitialized &&
IoC.Container.Kernel.HasComponent(mappedClass))
                constructor = null;
            else
            {
                try
                {
                    constructor =
ReflectHelper.GetDefaultConstructor(mappedClass);
                }
                catch (PropertyNotFoundException)
                {
                    log.Info(string.Format("no default (no-argument)
constructor for class: {0} (class must be instantiated by Interceptor)",
mappedClass.FullName));
                    constructor = null;
                }
            }
        }

        #region IInstantiator Members

        public object Instantiate(object id)
        {
            bool useEmbeddedIdentifierInstanceAsEntity = embeddedIdentifier
&& id != null && id.GetType().Equals(mappedClass);
            return useEmbeddedIdentifierInstanceAsEntity ? id :
Instantiate();
        }

        public object Instantiate()
        {
            if (ReflectHelper.IsAbstractClass(mappedClass))
            {
                throw new InstantiationException("Cannot instantiate
abstract class or interface: ", mappedClass);
            }
            else if (optimizer != null)
            {
                return optimizer.CreateInstance();
            }
            else if (mappedClass.IsValueType)
            {
                return Activator.CreateInstance(mappedClass, true);

            }
            else if (constructor == null)
            {
                var instance = IoC.IsInitialized ? IoC.Resolve(mappedClass)
: null;
                if (instance != null) return instance;

                throw new InstantiationException("No default constructor for
entity: ", mappedClass);
            }
            else
            {
                try
                {
                    return constructor.Invoke(null);
                }
                catch (Exception e)
                {
                    throw new InstantiationException("Could not instantiate
entity: ", e, mappedClass);
                }
            }
        }

        public bool IsInstance(object obj)
        {
            return mappedClass.IsInstanceOfType(obj) || (proxyInterface !=
null && proxyInterface.IsInstanceOfType(obj)); //this one needed only for
guessEntityMode()
        }

        #endregion

        #region IDeserializationCallback Members

        public void OnDeserialization(object sender)
        {
            constructor = ReflectHelper.GetDefaultConstructor(mappedClass);
        }

        #endregion
    }


2008/11/20 Fabio Maulo <[EMAIL PROTECTED]>

> 2008/11/19 Lee Henson <[EMAIL PROTECTED]>
>
>>  Do I need to code for optimizers etc?
>>
>
> Hi Lee.
> I don't know what you need.
> --
> Fabio Maulo
>
> >
>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"nhusers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/nhusers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to