/// <summary> /// /// </summary> /// <param name="componentClass"></param> /// <param name="propertyNames"></param> /// <param name="propertyGetters"></param> /// <param name="propertySetters"></param> /// <param name="foundCustomAcessor"></param> /// <param name="propertyTypes"></param> /// <param name="joinedFetch"></param> /// <param name="cascade"></param> /// <param name="parentProperty"></param> public ComponentType(System.Type componentClass, string[] propertyNames, IGetter[] propertyGetters, ISetter[] propertySetters, // currently not used, see the comment near the end of the method body bool foundCustomAcessor, IType[] propertyTypes, OuterJoinFetchStrategy[] joinedFetch, Cascades.CascadeStyle[] cascade, string parentProperty) { this.componentClass = componentClass; this.propertyTypes = propertyTypes; propertySpan = propertyNames.Length; getters = propertyGetters; setters = propertySetters; string[] getterNames = new string[propertySpan]; string[] setterNames = new string[propertySpan]; System.Type[] propTypes = new System.Type[propertySpan]; for (int i = 0; i < propertySpan; i++) { getterNames[i] = getters[i].PropertyName; setterNames[i] = setters[i].PropertyName; propTypes[i] = getters[i].ReturnType; } if (parentProperty == null) { parentSetter = null; parentGetter = null; } else { IPropertyAccessor pa = PropertyAccessorFactory.GetPropertyAccessor(null); parentSetter = pa.GetSetter(componentClass, parentProperty); parentGetter = pa.GetGetter(componentClass, parentProperty); } this.propertyNames = propertyNames; this.cascade = cascade; this.joinedFetch = joinedFetch; // NH: reflection optimizer works with custom accessors if (/*!foundCustomAcessor &&*/ Cfg.Environment.UseReflectionOptimizer) { this.getset = GetSetHelperFactory.Create(componentClass, setters, getters); } }
/// <summary> /// Build the generated code /// </summary> /// <param name="code">Generated code</param> /// <returns>An instance of the generated class</returns> private IGetSetHelper Build(string code) { CodeDomProvider provider = new CSharpCodeProvider(); #if NET_2_0 CompilerResults res = provider.CompileAssemblyFromSource(cp, new string[] { code }); #else ICodeCompiler compiler = provider.CreateCompiler(); CompilerResults res = compiler.CompileAssemblyFromSource(cp, code); #endif if (res.Errors.HasErrors) { log.Debug("Compiled with error:\n" + code); foreach (CompilerError e in res.Errors) { log.Debug( String.Format("Line:{0}, Column:{1} Message:{2}", e.Line, e.Column, e.ErrorText) ); } throw new InvalidOperationException(res.Errors[0].ErrorText); } else { if (log.IsDebugEnabled) { log.Debug("Compiled ok:\n" + code); } } Assembly assembly = res.CompiledAssembly; System.Type[] types = assembly.GetTypes(); IGetSetHelper getset = ( IGetSetHelper )assembly.CreateInstance(types[0].FullName, false, BindingFlags.CreateInstance, null, new object[] { setters, getters }, CultureInfo.InvariantCulture, null); return(getset); }
/// <summary> /// /// </summary> /// <param name="componentClass"></param> /// <param name="propertyNames"></param> /// <param name="propertyGetters"></param> /// <param name="propertySetters"></param> /// <param name="foundCustomAcessor"></param> /// <param name="propertyTypes"></param> /// <param name="joinedFetch"></param> /// <param name="cascade"></param> /// <param name="parentProperty"></param> public ComponentType( System.Type componentClass, string[ ] propertyNames, IGetter[ ] propertyGetters, ISetter[ ] propertySetters, // currently not used, see the comment near the end of the method body bool foundCustomAcessor, IType[ ] propertyTypes, OuterJoinFetchStrategy[ ] joinedFetch, Cascades.CascadeStyle[ ] cascade, string parentProperty) { this.componentClass = componentClass; this.propertyTypes = propertyTypes; propertySpan = propertyNames.Length; getters = propertyGetters; setters = propertySetters; string[ ] getterNames = new string[propertySpan]; string[ ] setterNames = new string[propertySpan]; System.Type[ ] propTypes = new System.Type[propertySpan]; for( int i = 0; i < propertySpan; i++ ) { getterNames[ i ] = getters[ i ].PropertyName; setterNames[ i ] = setters[ i ].PropertyName; propTypes[ i ] = getters[ i ].ReturnType; } if( parentProperty == null ) { parentSetter = null; parentGetter = null; } else { IPropertyAccessor pa = PropertyAccessorFactory.GetPropertyAccessor( null ); parentSetter = pa.GetSetter( componentClass, parentProperty ); parentGetter = pa.GetGetter( componentClass, parentProperty ); } this.propertyNames = propertyNames; this.cascade = cascade; this.joinedFetch = joinedFetch; // NH: reflection optimizer works with custom accessors if( /*!foundCustomAcessor &&*/ Cfg.Environment.UseReflectionOptimizer ) { this.getset = GetSetHelperFactory.Create(componentClass, setters, getters); } }
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; } }