public RuntimeDataAccessModelInfo(TypeDescriptorProvider typeDescriptorProvider, Assembly concreteAssembly, Assembly definitionAssembly) { this.TypeDescriptorProvider = typeDescriptorProvider; this.dataAccessModelType = typeDescriptorProvider.DataAccessModelType; Debug.Assert(dataAccessModelType.Assembly == definitionAssembly); this.ConcreteAssembly = concreteAssembly; this.DefinitionAssembly = definitionAssembly; var concreteDataAccessModelType = concreteAssembly.GetType(dataAccessModelType.Namespace + "." + dataAccessModelType.Name); this.dataAccessModelConstructor = Expression.Lambda <Func <DataAccessModel> >(Expression.Convert(Expression.New(concreteDataAccessModelType), dataAccessModelType)).Compile(); var typeProvider = new TypeDescriptorProvider(dataAccessModelType); foreach (var type in typeProvider.GetTypeDescriptors()) { var concreteType = concreteAssembly.GetType(type.Type.Namespace + "." + type.Type.Name); this.concreteTypesByType[type.Type] = concreteType; this.typesByConcreteType[concreteType] = type.Type; this.dataAccessObjectsTypes[type.Type] = TypeHelper.DataAccessObjectsType.MakeGenericType(type.Type); this.enumerableTypes[type.Type] = TypeHelper.IEnumerableType.MakeGenericType(type.Type); } }
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); }
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); }
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); }
private static string GetFileName(TypeDescriptorProvider typeDescriptorProvider, string cacheDirectory, string serializedConfiguration, out string fullhash) { var sha1 = SHA1.Create(); var modelAssembly = typeDescriptorProvider.DataAccessModelType.Assembly; var uniquelyReferencedAssemblies = new HashSet <Assembly> { typeof(DataAccessModel).Assembly, modelAssembly }; foreach (var type in typeDescriptorProvider.GetTypeDescriptors()) { var current = type.Type; while (current != null) { uniquelyReferencedAssemblies.Add(current.Assembly); current = current.BaseType; } } var bytes = Encoding.UTF8.GetBytes(serializedConfiguration); sha1.TransformBlock(bytes, 0, bytes.Length, null, 0); foreach (var assembly in uniquelyReferencedAssemblies.OrderBy(c => c.FullName)) { bytes = Encoding.UTF8.GetBytes(assembly.FullName); sha1.TransformBlock(bytes, 0, bytes.Length, null, 0); bytes = Encoding.UTF8.GetBytes(assembly.GetName().Version.ToString()); sha1.TransformBlock(bytes, 0, bytes.Length, null, 0); var path = StringUriUtils.GetScheme(assembly.CodeBase) == "file" ? new Uri(assembly.CodeBase).LocalPath : assembly.Location; if (path != null) { if (assembly.GetName().GetPublicKeyToken().Length == 0) { var fileInfo = new FileInfo(path); bytes = BitConverter.GetBytes(fileInfo.Length); sha1.TransformBlock(bytes, 0, bytes.Length, null, 0); bytes = BitConverter.GetBytes(fileInfo.LastWriteTimeUtc.Ticks); sha1.TransformBlock(bytes, 0, bytes.Length, null, 0); } } } sha1.TransformFinalBlock(bytes, 0, 0); var fileName = modelAssembly.Location == null?modelAssembly.GetName().Name : Path.GetFileNameWithoutExtension(modelAssembly.Location); cacheDirectory = cacheDirectory?.Trim(); var codebaseUri = new Uri(modelAssembly.CodeBase); var modelName = typeDescriptorProvider.DataAccessModelType.Name; if (modelAssembly.GetExportedTypes().Any(c => c.Name == modelName && c != typeDescriptorProvider.DataAccessModelType)) { modelName = typeDescriptorProvider.DataAccessModelType.FullName.Replace(".", "_"); } fullhash = TextConversion.ToHexString(sha1.Hash); fileName = $"{fileName}.{modelName}.Generated.dll"; cacheDirectory = !string.IsNullOrEmpty(cacheDirectory) ? cacheDirectory : !codebaseUri.IsFile ? Environment.CurrentDirectory : Path.GetDirectoryName(codebaseUri.LocalPath); return(Path.Combine(cacheDirectory, fileName)); }