// 6.0 TODO: Move to IProxyFactory public static void PostInstantiate( this IProxyFactory pf, string entityName, System.Type persistentClass, HashSet <System.Type> interfaces, MethodInfo getIdentifierMethod, MethodInfo setIdentifierMethod, IAbstractComponentType componentIdType, bool isClassProxy) { if (pf is AbstractProxyFactory apf) { apf.PostInstantiate( entityName, persistentClass, interfaces, getIdentifierMethod, setIdentifierMethod, componentIdType, isClassProxy); } else { #pragma warning disable 618 pf.PostInstantiate( entityName, persistentClass, interfaces, getIdentifierMethod, setIdentifierMethod, componentIdType); #pragma warning restore 618 } }
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 HashSet <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(he, "could not create proxy factory for:{0}", EntityName); pf = null; } return(pf); }
protected AbstractEntityPersister(PersistentClass persistentClass, ICacheConcurrencyStrategy cache, ISessionFactoryImplementor factory) { this.factory = factory; dialect = factory.Dialect; this.cache = cache; //sqlExceptionConverter = factory.SQLExceptionConverter; entityMetamodel = new EntityMetamodel(persistentClass, factory); // CLASS mappedClass = persistentClass.MappedClass; sqlWhereString = persistentClass.Where; sqlWhereStringTemplate = sqlWhereString == null ? null : Template.RenderWhereStringTemplate(sqlWhereString, Dialect, factory.SQLFunctionRegistry); batchSize = persistentClass.BatchSize; hasSubselectLoadableCollections = persistentClass.HasSubselectLoadableCollections; constructor = ReflectHelper.GetDefaultConstructor(mappedClass); // verify that the class has a default constructor if it is not abstract - it is considered // a mapping exception if the default ctor is missing. if (!entityMetamodel.IsAbstract && constructor == null) { throw new MappingException("The mapped class " + mappedClass.FullName + " must declare a default (no-arg) constructor."); } // IDENTIFIER hasEmbeddedIdentifier = persistentClass.HasEmbeddedIdentifier; IValue idValue = persistentClass.Identifier; if (persistentClass.HasIdentifierProperty) { Mapping.Property idProperty = persistentClass.IdentifierProperty; identifierSetter = idProperty.GetSetter(mappedClass); identifierGetter = idProperty.GetGetter(mappedClass); } else { identifierGetter = null; identifierSetter = null; } System.Type prox = persistentClass.ProxyInterface; MethodInfo proxySetIdentifierMethod = null; MethodInfo proxyGetIdentifierMethod = null; if (persistentClass.HasIdentifierProperty && prox != null) { Mapping.Property idProperty = persistentClass.IdentifierProperty; proxyGetIdentifierMethod = idProperty.GetGetter(prox).Method; proxySetIdentifierMethod = idProperty.GetSetter(prox).Method; } // HYDRATE SPAN hydrateSpan = persistentClass.PropertyClosureCollection.Count; // IDENTIFIER identifierColumnSpan = persistentClass.Identifier.ColumnSpan; rootTableKeyColumnNames = new string[identifierColumnSpan]; identifierAliases = new string[identifierColumnSpan]; loaderName = persistentClass.LoaderName; int i = 0; foreach (Column col in idValue.ColumnCollection) { rootTableKeyColumnNames[i] = col.GetQuotedName(factory.Dialect); identifierAliases[i] = col.GetAlias(Dialect, persistentClass.RootTable); i++; } // VERSION: if (persistentClass.IsVersioned) { foreach (Column col in persistentClass.Version.ColumnCollection) { versionColumnName = col.GetQuotedName(Dialect); break; //only happens once } } else { versionColumnName = null; } if (persistentClass.IsVersioned) { versionGetter = persistentClass.Version.GetGetter(mappedClass); versionType = (IVersionType) persistentClass.Version.Type; } else { versionGetter = null; versionType = null; } // PROPERTIES getters = new IGetter[hydrateSpan]; setters = new ISetter[hydrateSpan]; string[] setterNames = new string[hydrateSpan]; string[] getterNames = new string[hydrateSpan]; System.Type[] classes = new System.Type[hydrateSpan]; i = 0; // NH: reflection optimizer works with custom accessors //bool foundCustomAccessor = false; foreach (Mapping.Property prop in persistentClass.PropertyClosureCollection) { //if( !prop.IsBasicPropertyAccessor ) //{ // foundCustomAccessor = true; //} getters[i] = prop.GetGetter(mappedClass); setters[i] = prop.GetSetter(mappedClass); getterNames[i] = getters[i].PropertyName; setterNames[i] = setters[i].PropertyName; classes[i] = getters[i].ReturnType; string propertyName = prop.Name; gettersByPropertyName[propertyName] = getters[i]; settersByPropertyName[propertyName] = setters[i]; i++; } // PROPERTIES (FROM ABSTRACTENTITYPERSISTER SUBCLASSES) propertyColumnNames = new string[HydrateSpan][]; propertyColumnAliases = new string[HydrateSpan][]; propertyColumnSpans = new int[HydrateSpan]; propertyColumnFormulaTemplates = new string[HydrateSpan][]; propertyColumnUpdateable = new bool[HydrateSpan][]; propertyColumnInsertable = new bool[HydrateSpan][]; propertyUniqueness = new bool[HydrateSpan]; HashedSet thisClassProperties = new HashedSet(); i = 0; bool foundFormula = false; foreach (Mapping.Property prop in persistentClass.PropertyClosureCollection) { thisClassProperties.Add(prop); int span = prop.ColumnSpan; propertyColumnSpans[i] = span; string[] colNames = new string[span]; string[] colAliases = new string[span]; string[] templates = new string[span]; int k = 0; foreach (ISelectable thing in prop.ColumnCollection) { colAliases[k] = thing.GetAlias(factory.Dialect, prop.Value.Table); if (thing.IsFormula) { foundFormula = true; templates[k] = thing.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry); } else { colNames[k] = thing.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry); } k++; } propertyColumnNames[i] = colNames; propertyColumnFormulaTemplates[i] = templates; propertyColumnAliases[i] = colAliases; propertyColumnInsertable[i] = prop.Value.ColumnInsertability; propertyColumnUpdateable[i] = prop.Value.ColumnUpdateability; propertyUniqueness[i] = prop.Value.IsUnique; i++; } hasFormulaProperties = foundFormula; // NH: reflection optimizer works with custom accessors if (Environment.UseReflectionOptimizer) { optimizer = Environment.BytecodeProvider.GetReflectionOptimizer(MappedClass, Getters, Setters); } // SUBCLASS PROPERTY CLOSURE ArrayList columns = new ArrayList(); //this.subclassColumnClosure ArrayList aliases = new ArrayList(); ArrayList formulaAliases = new ArrayList(); ArrayList formulaTemplates = new ArrayList(); ArrayList types = new ArrayList(); //this.subclassPropertyTypeClosure ArrayList names = new ArrayList(); //this.subclassPropertyNameClosure ArrayList subclassTemplates = new ArrayList(); ArrayList propColumns = new ArrayList(); //this.subclassPropertyColumnNameClosure ArrayList joinedFetchesList = new ArrayList(); //this.subclassPropertyEnableJoinedFetch ArrayList cascades = new ArrayList(); ArrayList definedBySubclass = new ArrayList(); // this.propertyDefinedOnSubclass ArrayList formulas = new ArrayList(); ArrayList propNullables = new ArrayList(); foreach (Mapping.Property prop in persistentClass.SubclassPropertyClosureCollection) { names.Add(prop.Name); bool isDefinedBySubclass = !thisClassProperties.Contains(prop); definedBySubclass.Add(isDefinedBySubclass); propNullables.Add(prop.IsOptional || isDefinedBySubclass); //TODO: is this completely correct? types.Add(prop.Type); string[] cols = new string[prop.ColumnSpan]; string[] forms = new string[prop.ColumnSpan]; int[] colnos = new int[prop.ColumnSpan]; int[] formnos = new int[prop.ColumnSpan]; int l = 0; foreach (ISelectable thing in prop.ColumnCollection) { if (thing.IsFormula) { string template = thing.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry); formnos[l] = formulaTemplates.Count; colnos[l] = -1; formulaTemplates.Add(template); forms[l] = template; formulas.Add(thing.GetText(factory.Dialect)); formulaAliases.Add(thing.GetAlias(factory.Dialect)); // TODO H3: formulasLazy.add( lazy ); } else { String colName = thing.GetTemplate(factory.Dialect, factory.SQLFunctionRegistry); colnos[l] = columns.Count; //before add :-) formnos[l] = -1; columns.Add(colName); cols[l] = colName; aliases.Add(thing.GetAlias(factory.Dialect, prop.Value.Table)); // TODO H3: columnsLazy.add( lazy ); // TODO H3: columnSelectables.add( new Boolean( prop.isSelectable() ) ); } l++; } propColumns.Add(cols); subclassTemplates.Add(forms); //propColumnNumbers.Add( colnos ); //propFormulaNumbers.Add( formnos ); joinedFetchesList.Add(prop.Value.FetchMode); cascades.Add(prop.CascadeStyle); } subclassColumnClosure = (string[]) columns.ToArray(typeof(string)); subclassFormulaClosure = (string[]) formulas.ToArray(typeof(string)); subclassFormulaTemplateClosure = (string[]) formulaTemplates.ToArray(typeof(string)); subclassPropertyTypeClosure = (IType[]) types.ToArray(typeof(IType)); subclassColumnAliasClosure = (string[]) aliases.ToArray(typeof(string)); subclassFormulaAliasClosure = (string[]) formulaAliases.ToArray(typeof(string)); subclassPropertyNameClosure = (string[]) names.ToArray(typeof(string)); subclassPropertyNullabilityClosure = (bool[]) propNullables.ToArray(typeof(bool)); subclassPropertyFormulaTemplateClosure = ArrayHelper.To2DStringArray(subclassTemplates); subclassPropertyColumnNameClosure = (string[][]) propColumns.ToArray(typeof(string[])); subclassPropertyCascadeStyleClosure = new Cascades.CascadeStyle[cascades.Count]; int m = 0; foreach (Cascades.CascadeStyle cs in cascades) { subclassPropertyCascadeStyleClosure[m++] = cs; } subclassPropertyFetchModeClosure = new FetchMode[joinedFetchesList.Count]; m = 0; foreach (FetchMode qq in joinedFetchesList) { subclassPropertyFetchModeClosure[m++] = qq; } propertyDefinedOnSubclass = new bool[definedBySubclass.Count]; m = 0; foreach (bool val in definedBySubclass) { propertyDefinedOnSubclass[m++] = val; } // CALLBACK INTERFACES implementsLifecycle = typeof(ILifecycle).IsAssignableFrom(mappedClass); implementsValidatable = typeof(IValidatable).IsAssignableFrom(mappedClass); // PROXIES concreteProxyClass = persistentClass.ProxyInterface; bool hasProxy = concreteProxyClass != null; if (hasProxy) { HashedSet proxyInterfaces = new HashedSet(); proxyInterfaces.Add(typeof(INHibernateProxy)); if (!mappedClass.Equals(concreteProxyClass)) { if (!concreteProxyClass.IsInterface) { throw new MappingException( "proxy must be either an interface, or the class itself: " + mappedClass.FullName); } proxyInterfaces.Add(concreteProxyClass); } if (mappedClass.IsInterface) { proxyInterfaces.Add(mappedClass); } if (HasProxy) { foreach (Subclass subclass in persistentClass.SubclassCollection) { System.Type subclassProxy = subclass.ProxyInterface; if (subclassProxy == null) { throw new MappingException("All subclasses must also have proxies: " + mappedClass.Name); } if (!subclass.MappedClass.Equals(subclassProxy)) { proxyInterfaces.Add(subclassProxy); } } } if (HasProxy) { proxyFactory = CreateProxyFactory(); proxyFactory.PostInstantiate(mappedClass, proxyInterfaces, proxyGetIdentifierMethod, proxySetIdentifierMethod); } else { proxyFactory = null; } } else { proxyFactory = null; } // Handle any filters applied to the class level filterHelper = new FilterHelper(persistentClass.FilterMap, factory.Dialect, factory.SQLFunctionRegistry); }
protected AbstractEntityPersister( PersistentClass model, ISessionFactoryImplementor factory ) { dialect = factory.Dialect; //sqlExceptionConverter = factory.SQLExceptionConverter; // CLASS className = model.MappedClass.FullName; rootClassName = model.RootClazz.Name; mappedClass = model.MappedClass; mutable = model.IsMutable; selectBeforeUpdate = model.SelectBeforeUpdate; dynamicUpdate = model.DynamicUpdate; dynamicInsert = model.DynamicInsert; sqlWhereString = model.Where; sqlWhereStringTemplate = sqlWhereString == null ? null : Template.RenderWhereStringTemplate( sqlWhereString, Dialect ); polymorphic = model.IsPolymorphic; explicitPolymorphism = model.IsExplicitPolymorphism; inherited = model.IsInherited; superclass = inherited ? model.Superclass.MappedClass : null; hasSubclasses = model.HasSubclasses; batchSize = model.BatchSize; constructor = ReflectHelper.GetDefaultConstructor( mappedClass ); abstractClass = ReflectHelper.IsAbstractClass( mappedClass ); entityType = NHibernateUtil.Entity( mappedClass ); optimisticLockMode = model.OptimisticLockMode; if( optimisticLockMode > OptimisticLockMode.Version && !dynamicUpdate ) { throw new MappingException( string.Format( "optimistic-lock setting requires dynamic-update=\'true\': {0}", className ) ); } // verify that the class has a default constructor if it is not abstract - it is considered // a mapping exception if the default ctor is missing. if( abstractClass == false && constructor == null ) { throw new MappingException( "The mapped class " + mappedClass.FullName + " must declare a default (no-arg) constructor." ); } // IDENTIFIER hasEmbeddedIdentifier = model.HasEmbeddedIdentifier; IValue idValue = model.Identifier; identifierType = idValue.Type; if( model.HasIdentifierProperty ) { Mapping.Property idProperty = model.IdentifierProperty; identifierPropertyName = idProperty.Name; identifierSetter = idProperty.GetSetter( mappedClass ); identifierGetter = idProperty.GetGetter( mappedClass ); } else { identifierPropertyName = null; identifierGetter = null; identifierSetter = null; } System.Type prox = model.ProxyInterface; MethodInfo proxySetIdentifierMethod = null; MethodInfo proxyGetIdentifierMethod = null; if( model.HasIdentifierProperty && prox != null ) { Mapping.Property idProperty = model.IdentifierProperty; PropertyInfo getIdPropertyInfo = idProperty.GetGetter( prox ).Property; if( getIdPropertyInfo != null ) { proxyGetIdentifierMethod = getIdPropertyInfo.GetGetMethod( true ); } PropertyInfo setIdPropertyInfo = idProperty.GetSetter( prox ).Property; if( setIdPropertyInfo != null ) { proxySetIdentifierMethod = setIdPropertyInfo.GetSetMethod( true ); } } // HYDRATE SPAN hydrateSpan = model.PropertyClosureCollection.Count; // IDENTIFIER int idColumnSpan = model.Identifier.ColumnSpan; identifierColumnNames = new string[idColumnSpan]; identifierAliases = new string[idColumnSpan]; int i = 0; foreach( Column col in idValue.ColumnCollection ) { identifierColumnNames[ i ] = col.GetQuotedName( Dialect ); identifierAliases[ i ] = col.Alias( Dialect ); i++; } // GENERATOR identifierGenerator = model.Identifier.CreateIdentifierGenerator( Dialect ); useIdentityColumn = identifierGenerator is IdentityGenerator; identitySelectString = useIdentityColumn ? dialect.IdentitySelectString : null; // UNSAVED-VALUE: unsavedIdentifierValue = UnsavedValueFactory.GetUnsavedIdentifierValue( model.Identifier.NullValue, identifierGetter, identifierType, constructor ); // VERSION: if( model.IsVersioned ) { foreach( Column col in model.Version.ColumnCollection ) { versionColumnName = col.GetQuotedName( Dialect ); break; //only happens once } } else { versionColumnName = null; } if( model.IsVersioned ) { //versionPropertyName = model.Version.Name; versioned = true; versionGetter = model.Version.GetGetter( mappedClass ); versionType = ( IVersionType ) model.Version.Type; } else { //versionPropertyName = null; versioned = false; versionGetter = null; versionType = null; } // VERSION UNSAVED-VALUE: unsavedVersionValue = model.IsVersioned ? UnsavedValueFactory.GetUnsavedVersionValue( model.Version.NullValue, versionGetter, versionType, constructor ) : Cascades.VersionValue.VersionUndefined; // PROPERTIES propertyTypes = new IType[hydrateSpan]; propertyNames = new string[hydrateSpan]; propertyUpdateability = new bool[hydrateSpan]; propertyInsertability = new bool[hydrateSpan]; propertyNullability = new bool[hydrateSpan]; getters = new IGetter[hydrateSpan]; setters = new ISetter[hydrateSpan]; cascadeStyles = new Cascades.CascadeStyle[hydrateSpan]; string[ ] setterNames = new string[hydrateSpan]; string[ ] getterNames = new string[hydrateSpan]; System.Type[ ] types = new System.Type[hydrateSpan]; i = 0; int tempVersionProperty = -66; bool foundCascade = false; bool foundCustomAccessor = false; foreach( Mapping.Property prop in model.PropertyClosureCollection ) { if( prop == model.Version ) { tempVersionProperty = i; } propertyNames[ i ] = prop.Name; if( !prop.IsBasicPropertyAccessor ) { foundCustomAccessor = true; } getters[ i ] = prop.GetGetter( mappedClass ); setters[ i ] = prop.GetSetter( mappedClass ); getterNames[ i ] = getters[ i ].PropertyName; setterNames[ i ] = setters[ i ].PropertyName; types[ i ] = getters[ i ].ReturnType; propertyTypes[ i ] = prop.Type; propertyUpdateability[ i ] = prop.IsUpdateable; propertyInsertability[ i ] = prop.IsInsertable; propertyNullability[ i ] = prop.IsNullable; gettersByPropertyName[ propertyNames[ i ] ] = getters[ i ]; settersByPropertyName[ propertyNames[ i ] ] = setters[ i ]; typesByPropertyName[ propertyNames[ i ] ] = propertyTypes[ i ]; cascadeStyles[ i ] = prop.CascadeStyle; if( cascadeStyles[ i ] != Cascades.CascadeStyle.StyleNone ) { foundCascade = true; } i++; } // NH: reflection optimizer works with custom accessors if( /*!foundCustomAccessor &&*/ Cfg.Environment.UseReflectionOptimizer ) { getset = GetSetHelperFactory.Create( MappedClass, Setters, Getters ); } hasCascades = foundCascade; versionProperty = tempVersionProperty; // CALLBACK INTERFACES implementsLifecycle = typeof( ILifecycle ).IsAssignableFrom( mappedClass ); implementsValidatable = typeof( IValidatable ).IsAssignableFrom( mappedClass ); cache = model.Cache; hasCollections = InitHasCollections(); // PROXIES concreteProxyClass = model.ProxyInterface; hasProxy = concreteProxyClass != null; if( hasProxy ) { HashedSet proxyInterfaces = new HashedSet(); proxyInterfaces.Add( typeof( INHibernateProxy ) ); if( !mappedClass.Equals( concreteProxyClass ) ) { if( !concreteProxyClass.IsInterface ) { throw new MappingException( "proxy must be either an interface, or the class itself: " + mappedClass.FullName ); } proxyInterfaces.Add( concreteProxyClass ); } if( mappedClass.IsInterface ) { proxyInterfaces.Add( mappedClass ); } if( hasProxy ) { foreach( Subclass subclass in model.SubclassCollection ) { System.Type subclassProxy = subclass.ProxyInterface; if( subclassProxy == null ) { throw new MappingException( "All subclasses must also have proxies: " + mappedClass.Name ); } if( !subclass.MappedClass.Equals( subclassProxy ) ) { proxyInterfaces.Add( subclassProxy ); } } } if( hasProxy ) { proxyFactory = CreateProxyFactory(); proxyFactory.PostInstantiate( mappedClass, proxyInterfaces, proxyGetIdentifierMethod, proxySetIdentifierMethod ); } else { proxyFactory = null; } } else { proxyFactory = null; } }