/// <summary> /// This method will return type given by the dataTypeDescriptor. /// If the data type does not exist, one will be dynamically /// runtime code generated. /// </summary> /// <param name="dataTypeDescriptor"></param> /// <param name="forceReCompilation">If this is true a new type will be compiled regardless if one already exists.</param> /// <returns></returns> public static Type GetType(DataTypeDescriptor dataTypeDescriptor, bool forceReCompilation = false) { bool codeGenerationNeeded; Type type = TryGetType(dataTypeDescriptor, forceReCompilation, out codeGenerationNeeded); if (type != null) { return type; } if (codeGenerationNeeded) { lock (_lock) { type = TypeManager.TryGetType(dataTypeDescriptor.GetFullInterfaceName()); if (type != null) return type; var codeGenerationBuilder = new CodeGenerationBuilder("DataInterface: " + dataTypeDescriptor.Name); InterfaceCodeGenerator.AddAssemblyReferences(codeGenerationBuilder, dataTypeDescriptor); InterfaceCodeGenerator.AddInterfaceTypeCode(codeGenerationBuilder, dataTypeDescriptor); IEnumerable<Type> types = CodeGenerationManager.CompileRuntimeTempTypes(codeGenerationBuilder); return types.Single(); } } return null; }
private static void Compile(CodeGenerationBuilder builder) { var compilerParameters = new CompilerParameters { GenerateExecutable = false, GenerateInMemory = false, OutputAssembly = CompositeGeneratedAssemblyPath, TempFiles = new TempFileCollection(TempAssemblyFolderPath) }; compilerParameters.ReferencedAssemblies.AddRangeIfNotContained(builder.AssemblyLocations.ToArray()); compilerParameters.AddAssemblyLocationsFromBin(); var codeCompileUnit = new CodeCompileUnit(); codeCompileUnit.Namespaces.AddRange(builder.Namespaces.ToArray()); for (int i = 0; i < NumberOfCompileRetries; i++) { var compiler = new CSharpCodeProvider(); CompilerResults compileResult = compiler.CompileAssemblyFromDom(compilerParameters, codeCompileUnit); if (compileResult.Errors.Count == 0) { return; } if (i == NumberOfCompileRetries - 1) { #if OUTPUT_SOURCE_CODE_ON_ERROR using (FileStream file = File.Create(Path.Combine(PathUtil.BaseDirectory, "output.cs"))) { using (var sw = new StreamWriter(file)) { compiler.GenerateCodeFromCompileUnit(codeCompileUnit, sw, new CodeGeneratorOptions()); } } #endif var sb = new StringBuilder(); foreach (CompilerError compilerError in compileResult.Errors) { if (compilerError.IsWarning) { continue; } string entry = "Compile error: " + compilerError.ErrorNumber + "(" + compilerError.Line + ")" + ": " + compilerError.ErrorText.Replace("{", "{{").Replace("}", "}}"); Log.LogError(LogTitle, entry); sb.AppendLine(entry); } throw new InvalidOperationException(sb.ToString()); } } }
/// <summary> /// Adds the assembly references required by the supplied <see cref="DataTypeDescriptor"/> to the supplied <see cref="CodeGenerationBuilder"/> /// </summary> /// <param name="codeGenerationBuilder">Assembly refences is added to this builder</param> /// <param name="dataTypeDescriptor">Data type descriptor which may contain references to assemblies</param> public static void AddAssemblyReferences(CodeGenerationBuilder codeGenerationBuilder, DataTypeDescriptor dataTypeDescriptor) { foreach (Assembly assembly in GetReferencedAssemblies(dataTypeDescriptor)) { codeGenerationBuilder.AddReference(assembly); } }
private static void PopulateBuilder(CodeGenerationBuilder builder) { foreach (ICodeProvider provider in CodeProviders) { provider.GetCodeToCompile(builder); } }
public void GetCodeToCompile(CodeGenerationBuilder builder) { foreach (DataTypeDescriptor dataTypeDescriptor in DataMetaDataFacade.GeneratedTypeDataTypeDescriptors) { InterfaceCodeGenerator.AddAssemblyReferences(builder, dataTypeDescriptor); InterfaceCodeGenerator.AddInterfaceTypeCode(builder, dataTypeDescriptor); } }
internal static void AddDataWrapperClassCode(CodeGenerationBuilder codeGenerationBuilder, Type interfaceType) { codeGenerationBuilder.AddReference(interfaceType.Assembly); DataTypeDescriptor dataTypeDescriptor = ReflectionBasedDescriptorBuilder.Build(interfaceType); AddDataWrapperClassCode(codeGenerationBuilder, dataTypeDescriptor); }
/// <summary> /// Adds the source code defined by <see cref="DataTypeDescriptor"/> to the supplied <see cref="CodeGenerationBuilder"/> /// </summary> /// <param name="codeGenerationBuilder">Source code is added to this builder</param> /// <param name="dataTypeDescriptor">Data type descriptor to convert into source code</param> public static void AddInterfaceTypeCode(CodeGenerationBuilder codeGenerationBuilder, DataTypeDescriptor dataTypeDescriptor) { var codeTypeDeclaration = CreateCodeTypeDeclaration(dataTypeDescriptor); var codeNamespace = new CodeNamespace(dataTypeDescriptor.Namespace); codeNamespace.Types.Add(codeTypeDeclaration); codeGenerationBuilder.AddNamespace(codeNamespace); }
public XmlDataProviderCodeBuilder(string providerName, CodeGenerationBuilder codeGenerationBuilder) { _codeGenerationBuilder = codeGenerationBuilder; _namespaceName = NamesCreator.MakeNamespaceName(providerName); AddCodeNamespaces(); }
internal static void AddPropertySerializerTypeCode(CodeGenerationBuilder codeGenerationBuilder, string propertyClassTypeName, IList<Tuple<string, Type>> properties) { codeGenerationBuilder.AddReference(typeof(EditorBrowsableAttribute).Assembly); codeGenerationBuilder.AddReference(typeof(StringConversionServices).Assembly); CodeTypeDeclaration codeTypeDeclaration = CreateCodeTypeDeclaration(propertyClassTypeName, properties); codeGenerationBuilder.AddType(NamespaceName, codeTypeDeclaration); }
private static Type CodeGeneratePropertySerializer(Type propertyClassType) { CodeGenerationBuilder codeGenerationBuilder = new CodeGenerationBuilder("PropertySerializer: " + propertyClassType.FullName); PropertySerializerTypeCodeGenerator.AddPropertySerializerTypeCode(codeGenerationBuilder, propertyClassType); IEnumerable<Type> types = CodeGenerationManager.CompileRuntimeTempTypes(codeGenerationBuilder); return types.Single(); }
internal static void AddEmptyDataClassTypeCode(CodeGenerationBuilder codeGenerationBuilder, DataTypeDescriptor dataTypeDescriptor, Type baseClassType = null, CodeAttributeDeclaration codeAttributeDeclaration = null) { Type interfaceType = DataTypeTypesManager.GetDataType(dataTypeDescriptor); if (interfaceType == null) return; if (baseClassType == null) baseClassType = typeof(EmptyDataClassBase); CodeTypeDeclaration codeTypeDeclaration = CreateCodeTypeDeclaration(dataTypeDescriptor, baseClassType, codeAttributeDeclaration); codeGenerationBuilder.AddType(NamespaceName, codeTypeDeclaration); }
internal static void AddDataWrapperClassCode(CodeGenerationBuilder codeGenerationBuilder, DataTypeDescriptor dataTypeDescriptor) { Type interfaceType = DataTypeTypesManager.GetDataType(dataTypeDescriptor); if (interfaceType == null) return; codeGenerationBuilder.AddReference(typeof(IDataWrapper).Assembly); codeGenerationBuilder.AddReference(typeof(EditorBrowsableAttribute).Assembly); CodeTypeDeclaration codeTypeDeclaration = CreateCodeTypeDeclaration(dataTypeDescriptor); codeGenerationBuilder.AddType(NamespaceName, codeTypeDeclaration); }
public void GetCodeToCompile(CodeGenerationBuilder builder) { foreach (DataTypeDescriptor dataTypeDescriptor in DataMetaDataFacade.AllDataTypeDescriptors) { if (!dataTypeDescriptor.ValidateRuntimeType()) { Log.LogError("DataWrapperClassCodeProvider", string.Format("The non code generated interface type '{0}' was not found, skipping code generation for that type", dataTypeDescriptor)); continue; } DataWrapperCodeGenerator.AddDataWrapperClassCode(builder, dataTypeDescriptor); } }
private static void Compile(CodeGenerationBuilder builder) { var compilerParameters = new CompilerParameters { GenerateExecutable = false, GenerateInMemory = false, OutputAssembly = CompositeGeneratedAssemblyPath, TempFiles = new TempFileCollection(TempAssemblyFolderPath) }; compilerParameters.ReferencedAssemblies.AddRangeIfNotContained(builder.AssemblyLocations.ToArray()); compilerParameters.AddAssemblyLocationsFromBin(); var codeCompileUnit = new CodeCompileUnit(); codeCompileUnit.Namespaces.AddRange(builder.Namespaces.ToArray()); for (var i = 0; i < NumberOfCompileRetries; i++) { var compiler = CSharpCodeProviderFactory.CreateCompiler(); CompilerResults compileResult = compiler.CompileAssemblyFromDom(compilerParameters, codeCompileUnit); if (!compileResult.Errors.HasErrors) { return; } if (i == NumberOfCompileRetries - 1) { OutputSourceCodeOnError(compiler, codeCompileUnit); var sb = new StringBuilder(); foreach (CompilerError compilerError in compileResult.Errors) { if (compilerError.IsWarning) { continue; } var entry = "Compile error: " + compilerError.ErrorNumber + "(" + compilerError.Line + ")" + ": " + compilerError.ErrorText.Replace("{", "{{").Replace("}", "}}"); Log.LogError(LogTitle, entry); sb.AppendLine(entry); } throw new InvalidOperationException(sb.ToString()); } } }
internal static void AddAssemblyReferences(CodeGenerationBuilder codeGenerationBuilder, DataTypeDescriptor dataTypeDescriptor) { Type interfaceType = DataTypeTypesManager.GetDataType(dataTypeDescriptor); if (interfaceType == null) return; codeGenerationBuilder.AddReference(typeof(EmptyDataClassBase).Assembly); codeGenerationBuilder.AddReference(typeof(EditorBrowsableAttribute).Assembly); codeGenerationBuilder.AddReference(interfaceType.Assembly); if (!string.IsNullOrEmpty(dataTypeDescriptor.BuildNewHandlerTypeName)) { Type buildeNewHandlerType = TypeManager.GetType(dataTypeDescriptor.BuildNewHandlerTypeName); codeGenerationBuilder.AddReference(buildeNewHandlerType.Assembly); } }
public void GetCodeToCompile(CodeGenerationBuilder builder) { foreach (DataTypeDescriptor dataTypeDescriptor in DataMetaDataFacade.AllDataTypeDescriptors) { if (!dataTypeDescriptor.ValidateRuntimeType()) { Log.LogError("EmptyDataClassCodeProvider", "The non code generated interface type '{0}' was not found, skipping code generation for that type", dataTypeDescriptor); continue; } if (string.IsNullOrEmpty(dataTypeDescriptor.BuildNewHandlerTypeName)) { EmptyDataClassCodeGenerator.AddAssemblyReferences(builder, dataTypeDescriptor); EmptyDataClassCodeGenerator.AddEmptyDataClassTypeCode(builder, dataTypeDescriptor); } } }
public static Type GetDataWrapperType(Type interfaceType) { Type wrapperType = TryGetWrapperType(interfaceType.FullName); if (wrapperType != null) return wrapperType; lock (_lock) { wrapperType = TryGetWrapperType(interfaceType.FullName); if (wrapperType != null) return wrapperType; var codeGenerationBuilder = new CodeGenerationBuilder("DataWrapper:" + interfaceType.FullName); DataWrapperCodeGenerator.AddDataWrapperClassCode(codeGenerationBuilder, interfaceType); IEnumerable<Type> types = CodeGenerationManager.CompileRuntimeTempTypes(codeGenerationBuilder); return types.Single(); } }
public static Type GetDataWrapperType(DataTypeDescriptor dataTypeDescriptor) { Type wrapperType = TryGetWrapperType(dataTypeDescriptor.GetFullInterfaceName()); if (wrapperType != null) return wrapperType; lock (_lock) { wrapperType = TryGetWrapperType(dataTypeDescriptor.GetFullInterfaceName()); if (wrapperType != null) return wrapperType; var codeGenerationBuilder = new CodeGenerationBuilder("DataWrapper:" + dataTypeDescriptor.GetFullInterfaceName()); DataWrapperCodeGenerator.AddDataWrapperClassCode(codeGenerationBuilder, dataTypeDescriptor); IEnumerable<Type> types = CodeGenerationManager.CompileRuntimeTempTypes(codeGenerationBuilder); return types.Single(); } }
/// <summary> /// This method will recompile Composite.Generated.dll and drop it into bin. /// </summary> /// <param name="forceGeneration"></param> public static void GenerateCompositeGeneratedAssembly(bool forceGeneration = false) { if (SuppressGeneration) { return; } if (forceGeneration || !_compositeGeneratedCompiled) { lock (_lock) { if (forceGeneration || !_compositeGeneratedCompiled) { Log.LogVerbose(LogTitle, $"Compiling new assembly in this application domain ({AppDomain.CurrentDomain.Id})"); int t1 = Environment.TickCount; var builder = new CodeGenerationBuilder("Composite.Generated.dll"); PopulateBuilder(builder); int t2 = Environment.TickCount; Compile(builder); int t3 = Environment.TickCount; int numberOfTypes = builder.Namespaces.SelectMany(f => f.Types.OfType <CodeTypeDeclaration>()).Count(); Log.LogVerbose(LogTitle, "Number of types build: " + numberOfTypes + "\nBuilding code dom: " + (t2 - t1) + "ms" + "\nCompiling code dom: " + (t3 - t2) + "ms" + "\nTotal compilation: " + (t3 - t1) + "ms"); _compositeGeneratedCompiled = true; return; } } } Log.LogVerbose(LogTitle, "New assembly already compiled by this application domain ({0})", AppDomain.CurrentDomain.Id); }
/// <summary> /// This method will compile the type defined in <paramref name="codeGenerationBuilder"/> /// and return the result types. These types exists in a temp assembly, that will be /// deleted when the app domain is terminated. /// </summary> /// <param name="codeGenerationBuilder"></param> /// <param name="verbose"></param> /// <returns></returns> public static IEnumerable<Type> CompileRuntimeTempTypes(CodeGenerationBuilder codeGenerationBuilder, bool verbose = true) { int t1 = Environment.TickCount; _compositeGeneratedCompiled = false; // When compiling a new type, Composite.Generated.dll should always be recompiled var compilerParameters = new CompilerParameters { GenerateExecutable = false, GenerateInMemory = false, OutputAssembly = Path.Combine(TempAssemblyFolderPath, Guid.NewGuid() + ".dll") }; compilerParameters.ReferencedAssemblies.AddRangeIfNotContained(codeGenerationBuilder.AssemblyLocations.ToArray()); compilerParameters.ReferencedAssemblies.AddRangeIfNotContained(_compiledAssemblies.Select(f => f.Location).ToArray()); compilerParameters.AddAssemblyLocationsFromBin(); var codeCompileUnit = new CodeCompileUnit(); codeCompileUnit.Namespaces.AddRange(codeGenerationBuilder.Namespaces.ToArray()); var compiler = new CSharpCodeProvider(); var compileResult = compiler.CompileAssemblyFromDom(compilerParameters, codeCompileUnit); if (compileResult.Errors.Count == 0) { Assembly resultAssembly = compileResult.CompiledAssembly; AddCompiledAssembly(resultAssembly); Type[] resultTypes = resultAssembly.GetTypes(); int t2 = Environment.TickCount; Log.LogVerbose(LogTitle, string.Format("Compile '{0}' in {1}ms", codeGenerationBuilder.DebugLabel, t2 - t1)); Log.LogVerbose(LogTitle, string.Format("Types from : {0}", compilerParameters.OutputAssembly)); foreach (Type resultType in resultTypes) { _compiledTypesByFullName[resultType.FullName] = resultType; } return resultTypes; } #if OUTPUT_SOURCE_CODE_ON_ERROR using (FileStream file = File.Create(Path.Combine(PathUtil.BaseDirectory, "output.cs"))) { using (var sw = new StreamWriter(file)) { compiler.GenerateCodeFromCompileUnit(codeCompileUnit, sw, new CodeGeneratorOptions()); } } #endif var failedAssemblyLoads = new List<Pair<string, Exception>>(); foreach (string assemblyLocation in compilerParameters.ReferencedAssemblies) { try { Assembly assembly = Assembly.LoadFrom(assemblyLocation); var types = assembly.GetTypes(); // Accessing GetTypes() to iterate classes } catch (Exception ex) { Exception exceptionToLog = ex; var loadException = ex as ReflectionTypeLoadException; if (loadException != null && loadException.LoaderExceptions != null && loadException.LoaderExceptions.Any()) { exceptionToLog = loadException.LoaderExceptions.First(); } failedAssemblyLoads.Add(new Pair<string, Exception>( assemblyLocation, exceptionToLog)); } } var sb = new StringBuilder(); failedAssemblyLoads.ForEach(asm => sb.AppendFormat("Failed to load dll: '{0}' : {1}", asm.First, asm.Second).AppendLine()); sb.AppendLine("Failed building: " + codeGenerationBuilder.DebugLabel); foreach (CompilerError compilerError in compileResult.Errors) { if (compilerError.IsWarning) continue; string entry = "Compile error: " + compilerError.ErrorNumber + "(" + compilerError.Line + ")" + ": " + compilerError.ErrorText.Replace("{", "{{").Replace("}", "}}"); if (verbose) { Log.LogError(LogTitle, entry); } sb.AppendLine(entry); } throw new InvalidOperationException(sb.ToString()); }
/// <summary> /// This method will compile the type defined in <paramref name="codeGenerationBuilder"/> /// and return the result types. These types exists in a temp assembly, that will be /// deleted when the app domain is terminated. /// </summary> /// <param name="codeGenerationBuilder"></param> /// <param name="verbose"></param> /// <returns></returns> public static IEnumerable <Type> CompileRuntimeTempTypes(CodeGenerationBuilder codeGenerationBuilder, bool verbose = true) { int t1 = Environment.TickCount; _compositeGeneratedCompiled = false; // When compiling a new type, Composite.Generated.dll should always be recompiled var compilerParameters = new CompilerParameters { GenerateExecutable = false, GenerateInMemory = false, OutputAssembly = Path.Combine(TempAssemblyFolderPath, Guid.NewGuid() + ".dll") }; compilerParameters.ReferencedAssemblies.AddRangeIfNotContained(codeGenerationBuilder.AssemblyLocations.ToArray()); compilerParameters.ReferencedAssemblies.AddRangeIfNotContained(_compiledAssemblies.Select(f => f.Location).ToArray()); compilerParameters.AddAssemblyLocationsFromBin(); var codeCompileUnit = new CodeCompileUnit(); codeCompileUnit.Namespaces.AddRange(codeGenerationBuilder.Namespaces.ToArray()); var compiler = new CSharpCodeProvider(); var compileResult = compiler.CompileAssemblyFromDom(compilerParameters, codeCompileUnit); if (compileResult.Errors.Count == 0) { Assembly resultAssembly = compileResult.CompiledAssembly; AddCompiledAssembly(resultAssembly); Type[] resultTypes = resultAssembly.GetTypes(); int t2 = Environment.TickCount; Log.LogVerbose(LogTitle, $"Compile '{codeGenerationBuilder.DebugLabel}' in {t2 - t1}ms"); Log.LogVerbose(LogTitle, $"Types from : {compilerParameters.OutputAssembly}"); foreach (Type resultType in resultTypes) { _compiledTypesByFullName[resultType.FullName] = resultType; } return(resultTypes); } #if OUTPUT_SOURCE_CODE_ON_ERROR using (FileStream file = File.Create(Path.Combine(PathUtil.BaseDirectory, "output.cs"))) { using (var sw = new StreamWriter(file)) { compiler.GenerateCodeFromCompileUnit(codeCompileUnit, sw, new CodeGeneratorOptions()); } } #endif var failedAssemblyLoads = LoadAssembliesToMemory(compilerParameters.ReferencedAssemblies); var sb = new StringBuilder(); failedAssemblyLoads.ForEach(asm => sb.AppendFormat("Failed to load dll: '{0}' : {1}", asm.First, asm.Second).AppendLine()); sb.AppendLine("Failed building: " + codeGenerationBuilder.DebugLabel); foreach (CompilerError compilerError in compileResult.Errors) { if (compilerError.IsWarning) { continue; } string entry = "Compile error: " + compilerError.ErrorNumber + "(" + compilerError.Line + ")" + ": " + compilerError.ErrorText.Replace("{", "{{").Replace("}", "}}"); if (verbose) { Log.LogError(LogTitle, entry); } sb.AppendLine(entry); } throw new InvalidOperationException(sb.ToString()); }
/// <summary> /// This method will recompile Composite.Generated.dll and drop it into bin. /// </summary> /// <param name="forceGeneration"></param> public static void GenerateCompositeGeneratedAssembly(bool forceGeneration = false) { if (SuppressGeneration) return; if (forceGeneration || !_compositeGeneratedCompiled) { lock (_lock) { if (forceGeneration || !_compositeGeneratedCompiled) { Log.LogVerbose(LogTitle, string.Format("Compiling new assembly in this application domain ({0})", AppDomain.CurrentDomain.Id)); int t1 = Environment.TickCount; var builder = new CodeGenerationBuilder("Composite.Generated.dll"); PopulateBuilder(builder); int t2 = Environment.TickCount; Compile(builder); int t3 = Environment.TickCount; int numberOfTypes = builder.Namespaces.SelectMany(f => f.Types.OfType<CodeTypeDeclaration>()).Count(); Log.LogVerbose(LogTitle, "Number of types build: " + numberOfTypes + "\nBuilding code dom: " + (t2 - t1) + "ms" + "\nCompiling code dom: " + (t3 - t2) + "ms" + "\nTotal compilation: " + (t3 - t1) + "ms"); _compositeGeneratedCompiled = true; return; } } } Log.LogVerbose(LogTitle, "New assembly already compiled by this application domain ({0})", AppDomain.CurrentDomain.Id); }
internal static Type CreateEmptyDataClassType(DataTypeDescriptor dataTypeDescriptor, Type baseClassType = null, CodeAttributeDeclaration codeAttributeDeclaration = null) { var codeGenerationBuilder = new CodeGenerationBuilder("EmptyDataClass: " + dataTypeDescriptor.Name); EmptyDataClassCodeGenerator.AddAssemblyReferences(codeGenerationBuilder, dataTypeDescriptor); EmptyDataClassCodeGenerator.AddEmptyDataClassTypeCode(codeGenerationBuilder, dataTypeDescriptor, baseClassType, codeAttributeDeclaration); IEnumerable<Type> types = CodeGenerationManager.CompileRuntimeTempTypes(codeGenerationBuilder); return types.Single(); }
private InterfaceGeneratedClassesInfo InitializeStoreTypes(InterfaceConfigurationElement element, Dictionary<DataTypeDescriptor, IEnumerable<SqlDataTypeStoreDataScope>> allSqlDataTypeStoreDataScopes, Type dataContextClass, bool forceCompile, ref bool dataContextRecompilationNeeded) { HelperClassesGenerationInfo toCompile = null; var result = InitializeStoreTypes(element, allSqlDataTypeStoreDataScopes, dataContextClass, null, forceCompile, ref dataContextRecompilationNeeded, ref toCompile); if (result != null && toCompile != null) { var codeGenerationBuilder = new CodeGenerationBuilder(_dataProviderContext.ProviderName + ":" + result.InterfaceType.FullName); toCompile.GenerateCodeAction(codeGenerationBuilder); var types = CodeGenerationManager.CompileRuntimeTempTypes(codeGenerationBuilder, false).ToArray(); toCompile.PopulateFieldsAction(types); } return result; }
public void GetCodeToCompile(CodeGenerationBuilder builder) { XmlDataProvider xmlDataProvider = (XmlDataProvider)DataProviderPluginFacade.GetDataProvider(ProviderName); xmlDataProvider.BuildAllCode(builder); }
private bool EnsureNeededTypes(DataTypeDescriptor dataTypeDescriptor, out Type dataProviderHelperType, out Type dataIdClassType, bool forceCompile = false) { lock (_lock) { // Getting the interface (ensuring that it exists) Type interfaceType = DataTypeTypesManager.GetDataType(dataTypeDescriptor); if (interfaceType == null) { dataProviderHelperType = null; dataIdClassType = null; return false; } string dataProviderHelperClassFullName, dataIdClassFullName; GetGeneratedClassNames(dataTypeDescriptor, out dataProviderHelperClassFullName, out dataIdClassFullName); dataProviderHelperType = TypeManager.TryGetType(dataProviderHelperClassFullName); dataIdClassType = TypeManager.TryGetType(dataIdClassFullName); if (!forceCompile) { forceCompile = CodeGenerationManager.IsRecompileNeeded(interfaceType, new[] { dataProviderHelperType, dataIdClassType }); } if (forceCompile) { var codeGenerationBuilder = new CodeGenerationBuilder(_dataProviderContext.ProviderName + ":" + dataTypeDescriptor.Name); // XmlDataProvider types var codeBuilder = new XmlDataProviderCodeBuilder(_dataProviderContext.ProviderName, codeGenerationBuilder); codeBuilder.AddDataType(dataTypeDescriptor); DataWrapperCodeGenerator.AddDataWrapperClassCode(codeGenerationBuilder, dataTypeDescriptor); IEnumerable<Type> types = CodeGenerationManager.CompileRuntimeTempTypes(codeGenerationBuilder, false); dataProviderHelperType = types.Single(f => f.FullName == dataProviderHelperClassFullName); dataIdClassType = types.Single(f => f.FullName == dataIdClassFullName); } return true; } }
private void CompileMissingTypes(IList<GeneratedTypesInfo> typesInfo) { // Compiling missing classes if (typesInfo.Any(s => s.CompilationNeeded)) { var codeGenerationBuilder = new CodeGenerationBuilder(_dataProviderContext.ProviderName + ":DataId and helper classes"); var codeBuilder = new XmlDataProviderCodeBuilder(_dataProviderContext.ProviderName, codeGenerationBuilder); foreach (var storeToLoad in typesInfo.Where(s => s.CompilationNeeded)) { codeBuilder.AddDataType(storeToLoad.DataTypeDescriptor); // Compiling some other classes for optimization DataWrapperCodeGenerator.AddDataWrapperClassCode(codeGenerationBuilder, storeToLoad.DataTypeDescriptor); EmptyDataClassCodeGenerator.AddEmptyDataClassTypeCode(codeGenerationBuilder, storeToLoad.DataTypeDescriptor); } var types = CodeGenerationManager.CompileRuntimeTempTypes(codeGenerationBuilder, false).ToDictionary(type => type.FullName); foreach (var storeToLoad in typesInfo.Where(s => s.CompilationNeeded)) { storeToLoad.DataIdClass = types[storeToLoad.DataIdClassName]; storeToLoad.DataProviderHelperClass = types[storeToLoad.DataProviderHelperClassName]; } } }
private static void Compile(CodeGenerationBuilder builder) { var compilerParameters = new CompilerParameters { GenerateExecutable = false, GenerateInMemory = false, OutputAssembly = CompositeGeneratedAssemblyPath, TempFiles = new TempFileCollection(TempAssemblyFolderPath) }; compilerParameters.ReferencedAssemblies.AddRangeIfNotContained(builder.AssemblyLocations.ToArray()); compilerParameters.AddAssemblyLocationsFromBin(); var codeCompileUnit = new CodeCompileUnit(); codeCompileUnit.Namespaces.AddRange(builder.Namespaces.ToArray()); for (int i = 0; i < NumberOfCompileRetries; i++) { var compiler = new CSharpCodeProvider(); CompilerResults compileResult = compiler.CompileAssemblyFromDom(compilerParameters, codeCompileUnit); if (compileResult.Errors.Count == 0) return; if (i == NumberOfCompileRetries - 1) { #if OUTPUT_SOURCE_CODE_ON_ERROR using (FileStream file = File.Create(Path.Combine(PathUtil.BaseDirectory, "output.cs"))) { using (var sw = new StreamWriter(file)) { compiler.GenerateCodeFromCompileUnit(codeCompileUnit, sw, new CodeGeneratorOptions()); } } #endif var sb = new StringBuilder(); foreach (CompilerError compilerError in compileResult.Errors) { if (compilerError.IsWarning) continue; string entry = "Compile error: " + compilerError.ErrorNumber + "(" + compilerError.Line + ")" + ": " + compilerError.ErrorText.Replace("{", "{{").Replace("}", "}}"); Log.LogError(LogTitle, entry); sb.AppendLine(entry); } throw new InvalidOperationException(sb.ToString()); } } }
private void InitializeExistingStores() { _compositeGeneratedAssembly = _compositeGeneratedAssembly ?? AssemblyFacade.GetGeneratedAssemblyFromBin(); _sqlDataTypeStoresContainer = new SqlDataTypeStoresContainer(_dataProviderContext.ProviderName, _connectionString, _sqlLoggingContext); Dictionary<DataTypeDescriptor, IEnumerable<SqlDataTypeStoreDataScope>> allSqlDataTypeStoreDataScopes = BuildAllExistingDataTypeStoreDataScopes(); var initializedStores = new List<InterfaceGeneratedClassesInfo>(); bool dataContextRecompilationNeeded = false; Type dataContextClass = TryLoadDataContext(ref dataContextRecompilationNeeded); var dataTypes = LoadDataTypes(_interfaceConfigurationElements); var compilationData = new List<HelperClassesGenerationInfo>(); foreach (InterfaceConfigurationElement element in _interfaceConfigurationElements) { HelperClassesGenerationInfo toCompile = null; var generatedClassesInfo = InitializeStoreTypes(element, allSqlDataTypeStoreDataScopes, dataContextClass, dataTypes, false, ref dataContextRecompilationNeeded, ref toCompile); if (generatedClassesInfo == null) continue; if (toCompile != null) { compilationData.Add(toCompile); } initializedStores.Add(generatedClassesInfo); } if (compilationData.Any()) { var codeGenerationBuilder = new CodeGenerationBuilder(_dataProviderContext.ProviderName + " : compiling missing classes"); foreach (var toCompile in compilationData) { toCompile.GenerateCodeAction(codeGenerationBuilder); } // Precompiling DataWrapper classes as well to improve loading time foreach (var interfaceType in dataTypes.Values) { if (DataWrapperTypeManager.TryGetWrapperType(interfaceType.FullName) == null) { DataWrapperCodeGenerator.AddDataWrapperClassCode(codeGenerationBuilder, interfaceType); } } var types = CodeGenerationManager.CompileRuntimeTempTypes(codeGenerationBuilder, false).ToArray(); foreach (var toCompile in compilationData) { toCompile.PopulateFieldsAction(types); } } if (dataContextRecompilationNeeded) { dataContextClass = DataContextAssembler.EmitDataContextClass( initializedStores .Where(s => s.Fields != null) .SelectMany(s => s.Fields.Values).Evaluate()); } _sqlDataTypeStoresContainer.DataContextClass = dataContextClass; foreach (var typeInfo in initializedStores) { var store = EmbedDataContextInfo(typeInfo, dataContextClass); AddDataTypeStore(store, true, true); } }
public void CreateStores(IReadOnlyCollection<DataTypeDescriptor> dataTypeDescriptors) { var types = DataTypeTypesManager.GetDataTypes(dataTypeDescriptors); foreach (var dataTypeDescriptor in dataTypeDescriptors) { if (InterfaceConfigurationManipulator.ConfigurationExists(_dataProviderContext.ProviderName, dataTypeDescriptor)) { throw new InvalidOperationException(string.Format("SqlDataProvider configuration already contains a interface named '{0}'. Remove it from the configuration and restart the application.", dataTypeDescriptor.TypeManagerTypeName)); } } // Creating Sql tables and adding to the configuration var configElements = new Dictionary<DataTypeDescriptor, InterfaceConfigurationElement>(); foreach (var dataTypeDescriptor in dataTypeDescriptors) { Type type = types[dataTypeDescriptor.DataTypeId]; Action<string> existingTablesValidator = tableName => { var errors = new StringBuilder(); var interfaceType = type; if (!ValidateTable(interfaceType, tableName, errors)) { throw new InvalidOperationException("Table '{0}' already exist but isn't valid: {1}".FormatWith(tableName, errors.ToString())); } }; SqlStoreManipulator.CreateStoresForType(dataTypeDescriptor, existingTablesValidator); InterfaceConfigurationElement element = InterfaceConfigurationManipulator.AddNew(_dataProviderContext.ProviderName, dataTypeDescriptor); _interfaceConfigurationElements.Add(element); configElements.Add(dataTypeDescriptor, element); } // Generating necessary classes and performing validation Dictionary<DataTypeDescriptor, IEnumerable<SqlDataTypeStoreDataScope>> allSqlDataTypeStoreDataScopes = BuildAllExistingDataTypeStoreDataScopes(); bool dataContextRecompilationNeeded = false; var toCompileList = new List<HelperClassesGenerationInfo>(); var generatedClassesInfo = new Dictionary<DataTypeDescriptor, InterfaceGeneratedClassesInfo>(); Type dataContextClass = _sqlDataTypeStoresContainer.DataContextClass; foreach (var dataTypeDescriptor in dataTypeDescriptors) { var element = configElements[dataTypeDescriptor]; // InitializeStoreResult initializeStoreResult = InitializeStore(element, allSqlDataTypeStoreDataScopes); HelperClassesGenerationInfo toCompile = null; var classesInfo = InitializeStoreTypes(element, allSqlDataTypeStoreDataScopes, dataContextClass, null, false, ref dataContextRecompilationNeeded, ref toCompile); if (classesInfo != null && toCompile != null) { toCompileList.Add(toCompile); generatedClassesInfo[dataTypeDescriptor] = classesInfo; } } // Compiling missing classes if (toCompileList.Any()) { var codeGenerationBuilder = new CodeGenerationBuilder(_dataProviderContext.ProviderName + ":CreateStores"); foreach (var toCompile in toCompileList) { toCompile.GenerateCodeAction(codeGenerationBuilder); } var generatedHelperClasses = CodeGenerationManager.CompileRuntimeTempTypes(codeGenerationBuilder, false).ToArray(); foreach (var toCompile in toCompileList) { toCompile.PopulateFieldsAction(generatedHelperClasses); } } // Emitting a new DataContext class if (dataContextRecompilationNeeded) { var newDataTypeIds = new HashSet<Guid>(dataTypeDescriptors.Select(d => d.DataTypeId)); _createdSqlDataTypeStoreTables.RemoveAll(f => newDataTypeIds.Contains(f.DataTypeId)); var fields = _createdSqlDataTypeStoreTables.Select(s => new Tuple<string, Type>(s.DataContextFieldName, s.DataContextFieldType)).ToList(); foreach (var classesInfo in generatedClassesInfo.Values) { fields.AddRange(classesInfo.Fields.Select(f => new Tuple<string, Type>(f.Value.FieldName, f.Value.FieldType))); } dataContextClass = DataContextAssembler.EmitDataContextClass(fields); UpdateCreatedSqlDataTypeStoreTables(dataContextClass); } _sqlDataTypeStoresContainer.DataContextClass = dataContextClass; // Registering the new type/tables foreach (var dataTypeDescriptor in dataTypeDescriptors) { InterfaceGeneratedClassesInfo classesInfo; if (!generatedClassesInfo.TryGetValue(dataTypeDescriptor, out classesInfo)) { throw new InvalidOperationException("No generated classes for data type '{0}' found".FormatWith(dataTypeDescriptor.Name)); } InitializeStoreResult initInfo = EmbedDataContextInfo(classesInfo, dataContextClass); AddDataTypeStore(initInfo, false); } }
internal static Dictionary<Guid, Type> GetDataTypes(IReadOnlyCollection<DataTypeDescriptor> dataTypeDescriptors) { var result = new Dictionary<Guid, Type>(); var toCompile = new List<DataTypeDescriptor>(); foreach (var dataTypeDescriptor in dataTypeDescriptors) { string typeFullName = dataTypeDescriptor.GetFullInterfaceName(); Type type = _LoadedDataTypes.FirstOrDefault(f => f.FullName == typeFullName); if (type == null) { bool compilationNeeded; type = InterfaceCodeManager.TryGetType(dataTypeDescriptor, false, out compilationNeeded); if (compilationNeeded) { toCompile.Add(dataTypeDescriptor); } } if (type != null) { result[dataTypeDescriptor.DataTypeId] = type; } } if (toCompile.Any()) { var codeGenerationBuilder = new CodeGenerationBuilder("DataTypeTypesManager:compiling missing interfaces"); foreach (var dataTypeDescriptor in toCompile) { InterfaceCodeGenerator.AddAssemblyReferences(codeGenerationBuilder, dataTypeDescriptor); InterfaceCodeGenerator.AddInterfaceTypeCode(codeGenerationBuilder, dataTypeDescriptor); } var types = CodeGenerationManager.CompileRuntimeTempTypes(codeGenerationBuilder); var typesMap = types.ToDictionary(type => type.FullName); foreach (var dataTypeDescriptor in toCompile) { var type = typesMap[dataTypeDescriptor.GetFullInterfaceName()]; result[dataTypeDescriptor.DataTypeId] = type; } } return result; }