public AssemblyKey(Type dataAccessModelType, DataAccessModelConfiguration configuration) { this.configuration = configuration; this.dataAccessModelType = dataAccessModelType; this.configurationHash = configuration.GetSha1(); this.configurationXml = XmlSerializer <DataAccessModelConfiguration> .New().SerializeToString(configuration); }
public BaseTests(string providerName) { this.ProviderName = providerName; XmlConfigurator.Configure(); try { if (providerName == "default") { model = DataAccessModel.BuildDataAccessModel <T>(); } else { configuration = this.Create(providerName, this.GetType().Name); model = DataAccessModel.BuildDataAccessModel <T>(configuration); } model.Create(DatabaseCreationOptions.DeleteExisting); } catch (Exception e) { Console.WriteLine("Exception while configuring provider: " + providerName); Console.WriteLine(e); Console.WriteLine(e.StackTrace); throw; } }
public override RuntimeDataAccessModelInfo GetDataAccessModelAssembly(Type dataAccessModelType, DataAccessModelConfiguration configuration) { var typeDescriptorProvider = new TypeDescriptorProvider(dataAccessModelType); var originalAssembly = dataAccessModelType.Assembly; var builtAssembly = BuildAssembly(typeDescriptorProvider, configuration); return new RuntimeDataAccessModelInfo(typeDescriptorProvider, builtAssembly, originalAssembly); }
public DataAccessModelConfigurationUniqueKey(DataAccessModelConfiguration config) { this.ConstraintDefaultsConfiguration = config.ConstraintDefaultsConfiguration; this.NamingTransforms = config.NamingTransforms; this.ReferencedTypes = config.ReferencedTypes; this.ValueTypesAutoImplicitDefault = config.ValueTypesAutoImplicitDefault; this.AlwaysSubmitDefaultValues = config.AlwaysSubmitDefaultValues; this.IncludeImplicitDefaultsInSchema = config.IncludeImplicitDefaultsInSchema; }
private static Assembly BuildAssembly(TypeDescriptorProvider typeDescriptorProvider, DataAccessModelConfiguration configuration) { DataAccessObjectTypeBuilder dataAccessObjectTypeBuilder; var hash = configuration.GetSha1(); var assemblyName = new AssemblyName(typeDescriptorProvider.DataAccessModelType.Assembly.GetName().Name + "." + typeDescriptorProvider.DataAccessModelType.Name); var sharedAssemblyName = new AssemblyName("Shaolinq.GeneratedDataAccessModel"); var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(sharedAssemblyName, AssemblyBuilderAccess.RunAndSave); var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, assemblyName.Name + "." + hash + ".dll"); var propertiesBuilder = moduleBuilder.DefineType("$$$DataAccessModelProperties", TypeAttributes.Class, typeof(object)); var assemblyBuildContext = new AssemblyBuildContext(assemblyBuilder, propertiesBuilder); var dataAccessModelTypeBuilder = new DataAccessModelTypeBuilder(assemblyBuildContext, moduleBuilder); dataAccessModelTypeBuilder.BuildTypePhase1(typeDescriptorProvider.DataAccessModelType); var typeDescriptors = typeDescriptorProvider.GetTypeDescriptors(); foreach (var typeDescriptor in typeDescriptors) { dataAccessObjectTypeBuilder = new DataAccessObjectTypeBuilder(typeDescriptorProvider, assemblyBuildContext, moduleBuilder, typeDescriptor.Type); dataAccessObjectTypeBuilder.Build(new DataAccessObjectTypeBuilder.TypeBuildContext(1)); } foreach (var typeDescriptor in typeDescriptors) { dataAccessObjectTypeBuilder = assemblyBuildContext.TypeBuilders[typeDescriptor.Type]; dataAccessObjectTypeBuilder.Build(new DataAccessObjectTypeBuilder.TypeBuildContext(2)); } assemblyBuildContext.DataAccessModelPropertiesTypeBuilder.CreateType(); dataAccessModelTypeBuilder.BuildTypePhase2(); bool saveConcreteAssembly; bool.TryParse(ConfigurationManager.AppSettings["Shaolinq.SaveConcreteAssembly"], out saveConcreteAssembly); #if DEBUG const bool isInDebugMode = true; #else const bool isInDebugMode = false; #endif // ReSharper disable once ConditionIsAlwaysTrueOrFalse if (saveConcreteAssembly || isInDebugMode) { ActionUtils.IgnoreExceptions(() => assemblyBuilder.Save(assemblyName + "." + hash + ".dll")); } return assemblyBuilder; }
public override RuntimeDataAccessModelInfo GetDataAccessModelAssembly(Type dataAccessModelType, DataAccessModelConfiguration configuration) { var key = new AssemblyKey(dataAccessModelType, configuration); RuntimeDataAccessModelInfo runtimeDataAccessModelInfo; lock (this.assemblyBuildInfosByKey) { if (!this.assemblyBuildInfosByKey.TryGetValue(key, out runtimeDataAccessModelInfo)) { runtimeDataAccessModelInfo = this.provider.GetDataAccessModelAssembly(dataAccessModelType, configuration); this.assemblyBuildInfosByKey[key] = runtimeDataAccessModelInfo; } } return runtimeDataAccessModelInfo; }
private static Assembly BuildAssembly(TypeDescriptorProvider typeDescriptorProvider, DataAccessModelConfiguration configuration) { DataAccessObjectTypeBuilder dataAccessObjectTypeBuilder; var configMd5 = configuration.GetMd5(); var assemblyName = new AssemblyName(typeDescriptorProvider.DataAccessModelType.Assembly.GetName().Name + "." + typeDescriptorProvider.DataAccessModelType.Name); var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave); var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, assemblyName.Name + "." + configMd5 + ".dll"); var assemblyBuildContext = new AssemblyBuildContext(assemblyBuilder); var dataAccessModelTypeBuilder = new DataAccessModelTypeBuilder(assemblyBuildContext, moduleBuilder); dataAccessModelTypeBuilder.BuildType(typeDescriptorProvider.DataAccessModelType); var typeDescriptors = typeDescriptorProvider.GetTypeDescriptors(); foreach (var typeDescriptor in typeDescriptors) { dataAccessObjectTypeBuilder = new DataAccessObjectTypeBuilder(typeDescriptorProvider, assemblyBuildContext, moduleBuilder, typeDescriptor.Type); dataAccessObjectTypeBuilder.Build(new DataAccessObjectTypeBuilder.TypeBuildContext(1)); } foreach (var typeDescriptor in typeDescriptors) { dataAccessObjectTypeBuilder = assemblyBuildContext.TypeBuilders[typeDescriptor.Type]; dataAccessObjectTypeBuilder.Build(new DataAccessObjectTypeBuilder.TypeBuildContext(2)); } bool saveConcreteAssembly; bool.TryParse(ConfigurationManager.AppSettings["Shaolinq.SaveConcreteAssembly"], out saveConcreteAssembly); #if DEBUG const bool isInDebugMode = true; #else const bool isInDebugMode = false; #endif if (saveConcreteAssembly || isInDebugMode) { ActionUtils.IgnoreExceptions(() => assemblyBuilder.Save(assemblyName + "." + configMd5 + ".dll")); } return assemblyBuilder; }
public static DataAccessModelConfiguration Create(string databaseName, string serverName, string userName, string password, bool poolConnections, string categories) { var retval = new DataAccessModelConfiguration { SqlDatabaseContextInfos = new SqlDatabaseContextInfo[] { new MySqlSqlDatabaseContextInfo { DatabaseName = databaseName, Categories = categories, ServerName = serverName, PoolConnections = poolConnections, UserName = userName, Password = password } }, ConstraintDefaultsConfiguration = { IndexedStringMaximumLength = 255 } }; return retval; }
public static DataAccessModelConfiguration Create(string databaseName, string serverName, string userName, string password, bool poolConnections, string categories) { var retval = new DataAccessModelConfiguration { SqlDatabaseContextInfos = new List <SqlDatabaseContextInfo> { new MySqlSqlDatabaseContextInfo { DatabaseName = databaseName, Categories = categories, ServerName = serverName, PoolConnections = poolConnections, UserName = userName, Password = password } }, ConstraintDefaultsConfiguration = { IndexedStringMaximumLength = 255 } }; return(retval); }
public abstract RuntimeDataAccessModelInfo GetDataAccessModelAssembly(Type dataAccessModelType, DataAccessModelConfiguration configuration);
public AssemblyKey(Type dataAccessModelType, DataAccessModelConfiguration configuration) : this(dataAccessModelType, configuration.GetMd5()) { }
private static Assembly BuildAssembly(TypeDescriptorProvider typeDescriptorProvider, DataAccessModelConfiguration configuration) { DataAccessObjectTypeBuilder dataAccessObjectTypeBuilder; var hash = configuration.GetSha1(); var assemblyName = new AssemblyName(typeDescriptorProvider.DataAccessModelType.Assembly.GetName().Name + "." + typeDescriptorProvider.DataAccessModelType.Name); var sharedAssemblyName = new AssemblyName("Shaolinq.GeneratedDataAccessModel"); var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(sharedAssemblyName, AssemblyBuilderAccess.RunAndSave); var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, assemblyName.Name + "." + hash + ".dll"); var propertiesBuilder = moduleBuilder.DefineType("$$$DataAccessModelProperties", TypeAttributes.Class, typeof(object)); var assemblyBuildContext = new AssemblyBuildContext(assemblyBuilder, propertiesBuilder); var dataAccessModelTypeBuilder = new DataAccessModelTypeBuilder(assemblyBuildContext, moduleBuilder); dataAccessModelTypeBuilder.BuildTypePhase1(typeDescriptorProvider.DataAccessModelType); var typeDescriptors = typeDescriptorProvider.GetTypeDescriptors(); foreach (var typeDescriptor in typeDescriptors) { dataAccessObjectTypeBuilder = new DataAccessObjectTypeBuilder(typeDescriptorProvider, assemblyBuildContext, moduleBuilder, typeDescriptor.Type); dataAccessObjectTypeBuilder.Build(new DataAccessObjectTypeBuilder.TypeBuildContext(1)); } foreach (var typeDescriptor in typeDescriptors) { dataAccessObjectTypeBuilder = assemblyBuildContext.TypeBuilders[typeDescriptor.Type]; dataAccessObjectTypeBuilder.Build(new DataAccessObjectTypeBuilder.TypeBuildContext(2)); } assemblyBuildContext.DataAccessModelPropertiesTypeBuilder.CreateType(); dataAccessModelTypeBuilder.BuildTypePhase2(); bool saveConcreteAssembly; bool.TryParse(ConfigurationManager.AppSettings["Shaolinq.SaveConcreteAssembly"], out saveConcreteAssembly); #if DEBUG const bool isInDebugMode = true; #else const bool isInDebugMode = false; #endif // ReSharper disable once ConditionIsAlwaysTrueOrFalse if (saveConcreteAssembly || isInDebugMode) { ActionUtils.IgnoreExceptions(() => assemblyBuilder.Save(assemblyName + "." + hash + ".dll")); } return(assemblyBuilder); }
public TypeDescriptorProvider(Type dataAccessModelType, DataAccessModelConfiguration configuration) { this.Configuration = configuration; this.DataAccessModelType = dataAccessModelType; var dataAccessModelAttribute = dataAccessModelType.GetFirstCustomAttribute <DataAccessModelAttribute>(true); if (typeof(DataAccessModel).IsAssignableFrom(dataAccessModelType) && dataAccessModelAttribute == null) { throw new InvalidDataAccessObjectModelDefinition("The DataAccessModel type '{0}' is missing a DataAccessModelAttribute", dataAccessModelType.Name); } foreach (var type in this.DataAccessModelType .GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy) .Where(c => c.PropertyType.GetGenericTypeDefinitionOrNull() == typeof(DataAccessObjects <>)) .Select(c => c.PropertyType.GetGenericArguments()[0])) { var currentType = type; while (currentType != null && currentType != typeof(DataAccessObject) && !(currentType.GetGenericTypeDefinitionOrNull() == typeof(DataAccessObject <>))) { var dataAccessObjectAttribute = currentType.GetFirstCustomAttribute <DataAccessObjectAttribute>(false); if (dataAccessObjectAttribute != null) { if (!this.typeDescriptorsByType.ContainsKey(currentType)) { if (!typeof(DataAccessObject).IsAssignableFrom(currentType)) { throw new InvalidDataAccessObjectModelDefinition("The type {0} is decorated with a [DataAccessObject] attribute but does not extend DataAccessObject<T>", currentType.Name); } var typeDescriptor = new TypeDescriptor(this, currentType); if (typeDescriptor.PrimaryKeyProperties.Count(c => c.PropertyType.IsNullableType()) > 0) { throw new InvalidDataAccessObjectModelDefinition("The type {0} illegally defines a nullable primary key", currentType.Name); } this.typeDescriptorsByType[currentType] = typeDescriptor; } } else { throw new InvalidDataAccessObjectModelDefinition("Type '{0}' does not have a DataAccessObject attribute", currentType); } currentType = currentType.BaseType; } } var typesSet = new HashSet <Type>(this.typeDescriptorsByType.Keys); var typesReferenced = this.typeDescriptorsByType .Values .SelectMany(c => c.PersistedPropertiesWithoutBackreferences) .Select(c => c.PropertyType) .Where(c => typeof(DataAccessObject).IsAssignableFrom(c)) .Distinct(); var first = typesReferenced.FirstOrDefault(c => !typesSet.Contains(c)); if (first != null) { throw new InvalidDataAccessModelDefinitionException($"Type {first.Name} is referenced but is not declared as a property {dataAccessModelType.Name}"); } // Enums this.enumTypeDescriptorsByType = this.typeDescriptorsByType .Values .SelectMany(c => c.PersistedPropertiesWithoutBackreferences) .Select(c => c.PropertyType.GetUnwrappedNullableType()) .Where(c => c.IsEnum) .Distinct() .Select(c => new EnumTypeDescriptor(c)) .ToDictionary(c => c.EnumType, c => c); // Resolve relationships foreach (var typeDescriptor in this.typeDescriptorsByType.Values) { foreach (var propertyDescriptor in typeDescriptor.RelationshipRelatedProperties.Where(c => c.IsRelatedDataAccessObjectsProperty)) { if (typeof(RelatedDataAccessObjects <>).IsAssignableFromIgnoreGenericParameters(propertyDescriptor.PropertyType)) { var currentType = propertyDescriptor.PropertyType; while (currentType != null && currentType.GetGenericTypeDefinitionOrNull() != typeof(RelatedDataAccessObjects <>)) { currentType = currentType?.BaseType; } if (currentType == null) { throw new InvalidOperationException("Code should be unreachable"); } var relatedTypeDescriptor = this.typeDescriptorsByType[currentType.GetSequenceElementType()]; var relatedProperty = relatedTypeDescriptor .RelationshipRelatedProperties .Where(c => c.IsBackReferenceProperty) .SingleOrDefault(c => c.PropertyName == propertyDescriptor.RelatedDataAccessObjectsAttribute.BackReferenceName); relatedProperty = relatedProperty ?? relatedTypeDescriptor .RelationshipRelatedProperties .Where(c => c.IsBackReferenceProperty) .Where(c => !c.PropertyTypeTypeDescriptor.RelationshipRelatedProperties.Any(d => string.Equals(d.RelatedDataAccessObjectsAttribute?.BackReferenceName, c.PropertyName, StringComparison.InvariantCultureIgnoreCase))) .SingleOrDefault(c => typeDescriptor.Type == c.PropertyType); relatedProperty = relatedProperty ?? relatedTypeDescriptor .RelationshipRelatedProperties .Where(c => c.IsBackReferenceProperty) .SingleOrDefault(c => typeDescriptor.Type.IsAssignableFrom(c.PropertyType)); typeDescriptor.AddRelationshipInfo(RelationshipType.ParentOfOneToMany, propertyDescriptor, relatedProperty); relatedTypeDescriptor.AddRelationshipInfo(RelationshipType.ChildOfOneToMany, relatedProperty, propertyDescriptor); } } } // Fill in column names foreach (var typeDescriptor in this.typeDescriptorsByType.Values) { foreach (var columnInfo in QueryBinder.GetColumnInfos(this, typeDescriptor.PersistedProperties.ToArray())) { typeDescriptor.propertyDescriptorByColumnName[columnInfo.ColumnName] = columnInfo.RootProperty; } } this.ModelTypeDescriptor = new ModelTypeDescriptor(this, dataAccessModelType); }
private static Assembly BuildAssembly(TypeDescriptorProvider typeDescriptorProvider, DataAccessModelConfiguration configuration) { DataAccessObjectTypeBuilder dataAccessObjectTypeBuilder; var serializedConfiguration = XmlSerializer <DataAccessModelConfigurationUniqueKey> .New().SerializeToString(new DataAccessModelConfigurationUniqueKey(configuration)); var filename = GetFileName(typeDescriptorProvider, configuration.GeneratedAssembliesSaveDirectory, serializedConfiguration, out var fullhash); if (configuration.SaveAndReuseGeneratedAssemblies ?? false) { if (filename != null && File.Exists(filename)) { var candidate = Assembly.LoadFile(filename); if (ReadResource(candidate, "configuration.xml") == serializedConfiguration && ReadResource(candidate, "sha1.txt") == fullhash) { return(candidate); } } } var filenameWithoutExtension = Path.GetFileNameWithoutExtension(filename); var typeDescriptors = typeDescriptorProvider.GetTypeDescriptors(); var assemblyName = new AssemblyName(filenameWithoutExtension); var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave, Path.GetDirectoryName(filename)); var moduleBuilder = assemblyBuilder.DefineDynamicModule(filenameWithoutExtension, filenameWithoutExtension + ".dll"); assemblyBuilder.SetCustomAttribute(new CustomAttributeBuilder(TypeUtils.GetConstructor(() => new GeneratedAssemblyAttribute()), Type.EmptyTypes)); var propertiesBuilder = moduleBuilder.DefineType("$$$DataAccessModelProperties", TypeAttributes.Class, typeof(object)); var assemblyBuildContext = new AssemblyBuildContext(assemblyBuilder, moduleBuilder, propertiesBuilder); var dataAccessModelTypeBuilder = new DataAccessModelTypeBuilder(assemblyBuildContext, moduleBuilder); dataAccessModelTypeBuilder.BuildTypePhase1(typeDescriptorProvider.DataAccessModelType); foreach (var typeDescriptor in typeDescriptors) { dataAccessObjectTypeBuilder = new DataAccessObjectTypeBuilder(typeDescriptorProvider, assemblyBuildContext, moduleBuilder, typeDescriptor.Type); dataAccessObjectTypeBuilder.Build(new DataAccessObjectTypeBuilder.TypeBuildContext(1)); } foreach (var typeDescriptor in typeDescriptors) { dataAccessObjectTypeBuilder = assemblyBuildContext.TypeBuilders[typeDescriptor.Type]; dataAccessObjectTypeBuilder.Build(new DataAccessObjectTypeBuilder.TypeBuildContext(2)); } assemblyBuildContext.DataAccessModelPropertiesTypeBuilder.CreateType(); assemblyBuildContext.FinishConstantsContainer(); assemblyBuildContext.ConstantsContainer.CreateType(); dataAccessModelTypeBuilder.BuildTypePhase2(); #if DEBUG const bool isInDebugMode = true; #else const bool isInDebugMode = false; #endif var saveAssembly = configuration.SaveAndReuseGeneratedAssemblies ?? !isInDebugMode; if (saveAssembly) { try { moduleBuilder.DefineManifestResource("configuration.xml", new MemoryStream(Encoding.UTF8.GetBytes(serializedConfiguration)), ResourceAttributes.Public); moduleBuilder.DefineManifestResource("sha1.txt", new MemoryStream(Encoding.UTF8.GetBytes(fullhash)), ResourceAttributes.Public); assemblyBuilder.Save(Path.GetFileName(filename)); } catch { } } return(assemblyBuilder); }
public override RuntimeDataAccessModelInfo GetDataAccessModelAssembly(Type dataAccessModelType, DataAccessModelConfiguration configuration) { var typeDescriptorProvider = new TypeDescriptorProvider(dataAccessModelType); var originalAssembly = dataAccessModelType.Assembly; var builtAssembly = BuildAssembly(typeDescriptorProvider, configuration); return(new RuntimeDataAccessModelInfo(typeDescriptorProvider, builtAssembly, originalAssembly)); }
public override RuntimeDataAccessModelInfo GetDataAccessModelAssembly(Type dataAccessModelType, DataAccessModelConfiguration configuration) { var key = new AssemblyKey(dataAccessModelType, configuration); RuntimeDataAccessModelInfo runtimeDataAccessModelInfo; lock (this.assemblyBuildInfosByKey) { if (!this.assemblyBuildInfosByKey.TryGetValue(key, out runtimeDataAccessModelInfo)) { runtimeDataAccessModelInfo = this.provider.GetDataAccessModelAssembly(dataAccessModelType, configuration); this.assemblyBuildInfosByKey[key] = runtimeDataAccessModelInfo; } } return(runtimeDataAccessModelInfo); }
public TypeDescriptorProvider(Type dataAccessModelType, DataAccessModelConfiguration configuration) { this.Configuration = configuration; this.DataAccessModelType = dataAccessModelType; var dataAccessModelAttribute = dataAccessModelType.GetFirstCustomAttribute<DataAccessModelAttribute>(true); if (typeof(DataAccessModel).IsAssignableFrom(dataAccessModelType) && dataAccessModelAttribute == null) { throw new InvalidDataAccessObjectModelDefinition("The DataAccessModel type '{0}' is missing a DataAccessModelAttribute", dataAccessModelType.Name); } foreach (var type in this.DataAccessModelType .GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy) .Where(c => c.PropertyType.GetGenericTypeDefinitionOrNull() == typeof(DataAccessObjects<>)) .Select(c => c.PropertyType.GetGenericArguments()[0])) { var currentType = type; while (currentType != null && currentType != typeof(DataAccessObject) && !(currentType.GetGenericTypeDefinitionOrNull() == typeof(DataAccessObject<>))) { var dataAccessObjectAttribute = currentType.GetFirstCustomAttribute<DataAccessObjectAttribute>(false); if (dataAccessObjectAttribute != null) { if (!this.typeDescriptorsByType.ContainsKey(currentType)) { if (!typeof(DataAccessObject).IsAssignableFrom(currentType)) { throw new InvalidDataAccessObjectModelDefinition("The type {0} is decorated with a [DataAccessObject] attribute but does not extend DataAccessObject<T>", currentType.Name); } var typeDescriptor = new TypeDescriptor(this, currentType); if (typeDescriptor.PrimaryKeyProperties.Count(c => c.PropertyType.IsNullableType()) > 0) { throw new InvalidDataAccessObjectModelDefinition("The type {0} illegally defines a nullable primary key", currentType.Name); } this.typeDescriptorsByType[currentType] = typeDescriptor; } } else { throw new InvalidDataAccessObjectModelDefinition("Type '{0}' does not have a DataAccessObject attribute", currentType); } currentType = currentType.BaseType; } } var typesSet = new HashSet<Type>(this.typeDescriptorsByType.Keys); var typesReferenced = this.typeDescriptorsByType .Values .SelectMany(c => c.PersistedPropertiesWithoutBackreferences) .Select(c => c.PropertyType) .Where(c => typeof(DataAccessObject).IsAssignableFrom(c)) .Distinct(); var first = typesReferenced.FirstOrDefault(c => !typesSet.Contains(c)); if (first != null) { throw new InvalidDataAccessModelDefinitionException($"Type {first.Name} is referenced but is not declared as a property {dataAccessModelType.Name}"); } // Enums this.enumTypeDescriptorsByType = this.typeDescriptorsByType .Values .SelectMany(c => c.PersistedPropertiesWithoutBackreferences) .Select(c => c.PropertyType.GetUnwrappedNullableType()) .Where(c => c.IsEnum) .Distinct() .Select(c => new EnumTypeDescriptor(c)) .ToDictionary(c => c.EnumType, c => c); // Resolve relationships foreach (var typeDescriptor in this.typeDescriptorsByType.Values) { foreach (var propertyDescriptor in typeDescriptor.RelationshipRelatedProperties.Where(c => c.IsRelatedDataAccessObjectsProperty)) { if (typeof(RelatedDataAccessObjects<>).IsAssignableFromIgnoreGenericParameters(propertyDescriptor.PropertyType)) { var currentType = propertyDescriptor.PropertyType; while (currentType != null && currentType.GetGenericTypeDefinitionOrNull() != typeof(RelatedDataAccessObjects<>)) { currentType = currentType?.BaseType; } if (currentType == null) { throw new InvalidOperationException("Code should be unreachable"); } var relatedTypeDescriptor = this.typeDescriptorsByType[currentType.GetSequenceElementType()]; var relatedProperty = relatedTypeDescriptor .RelationshipRelatedProperties .Where(c => c.IsBackReferenceProperty) .SingleOrDefault(c => c.PropertyName == propertyDescriptor.RelatedDataAccessObjectsAttribute.BackReferenceName); relatedProperty = relatedProperty ?? relatedTypeDescriptor .RelationshipRelatedProperties .Where(c => c.IsBackReferenceProperty) .Where(c => !c.PropertyTypeTypeDescriptor.RelationshipRelatedProperties.Any(d => string.Equals(d.RelatedDataAccessObjectsAttribute?.BackReferenceName, c.PropertyName, StringComparison.InvariantCultureIgnoreCase))) .SingleOrDefault(c => typeDescriptor.Type == c.PropertyType); relatedProperty = relatedProperty ?? relatedTypeDescriptor .RelationshipRelatedProperties .Where(c => c.IsBackReferenceProperty) .SingleOrDefault(c => typeDescriptor.Type.IsAssignableFrom(c.PropertyType)); typeDescriptor.AddRelationshipInfo(RelationshipType.ParentOfOneToMany, propertyDescriptor, relatedProperty); relatedTypeDescriptor.AddRelationshipInfo(RelationshipType.ChildOfOneToMany, relatedProperty, propertyDescriptor); } } } // Fill in column names foreach (var typeDescriptor in typeDescriptorsByType.Values) { foreach (var columnInfo in QueryBinder.GetColumnInfos(this, typeDescriptor.PersistedProperties.ToArray())) { typeDescriptor.propertyDescriptorByColumnName[columnInfo.ColumnName] = columnInfo.RootProperty; } } this.ModelTypeDescriptor = new ModelTypeDescriptor(this, dataAccessModelType); }
private static Assembly BuildAssembly(TypeDescriptorProvider typeDescriptorProvider, DataAccessModelConfiguration configuration) { DataAccessObjectTypeBuilder dataAccessObjectTypeBuilder; var configMd5 = configuration.GetMd5(); var assemblyName = new AssemblyName(typeDescriptorProvider.DataAccessModelType.Assembly.GetName().Name + "." + typeDescriptorProvider.DataAccessModelType.Name); var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave); var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, assemblyName.Name + "." + configMd5 + ".dll"); var assemblyBuildContext = new AssemblyBuildContext(assemblyBuilder); var dataAccessModelTypeBuilder = new DataAccessModelTypeBuilder(assemblyBuildContext, moduleBuilder); dataAccessModelTypeBuilder.BuildType(typeDescriptorProvider.DataAccessModelType); var typeDescriptors = typeDescriptorProvider.GetTypeDescriptors(); foreach (var typeDescriptor in typeDescriptors) { dataAccessObjectTypeBuilder = new DataAccessObjectTypeBuilder(typeDescriptorProvider, assemblyBuildContext, moduleBuilder, typeDescriptor.Type); dataAccessObjectTypeBuilder.Build(new DataAccessObjectTypeBuilder.TypeBuildContext(1)); } foreach (var typeDescriptor in typeDescriptors) { dataAccessObjectTypeBuilder = assemblyBuildContext.TypeBuilders[typeDescriptor.Type]; dataAccessObjectTypeBuilder.Build(new DataAccessObjectTypeBuilder.TypeBuildContext(2)); } bool saveConcreteAssembly; bool.TryParse(ConfigurationManager.AppSettings["Shaolinq.SaveConcreteAssembly"], out saveConcreteAssembly); #if DEBUG const bool isInDebugMode = true; #else const bool isInDebugMode = false; #endif if (saveConcreteAssembly || isInDebugMode) { ActionUtils.IgnoreExceptions(() => assemblyBuilder.Save(assemblyName + "." + configMd5 + ".dll")); } return(assemblyBuilder); }
public override RuntimeDataAccessModelInfo GetDataAccessModelAssembly(Type dataAccessModelType, DataAccessModelConfiguration configuration) { var key = new AssemblyKey(dataAccessModelType, new DataAccessModelConfigurationUniqueKey(configuration)); lock (this.buildingSet) { while (true) { if (this.assemblyBuildInfosByKey.TryGetValue(key, out var runtimeDataAccessModelInfo)) { return(runtimeDataAccessModelInfo); } if (this.buildingSet.Contains(key)) { Monitor.Wait(this.buildingSet); continue; } try { this.buildingSet.Add(key); runtimeDataAccessModelInfo = this.provider.GetDataAccessModelAssembly(dataAccessModelType, configuration); this.assemblyBuildInfosByKey[key] = runtimeDataAccessModelInfo; return(runtimeDataAccessModelInfo); } finally { this.buildingSet.Remove(key); Monitor.PulseAll(this.buildingSet); } } } }