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()); } } }
private static CompatibilityCheckResult CheckAgainstAppCode(DataTypeDescriptor dataTypeDescriptorToTest, bool includeDataTypeDescriptor) { var filesToCompile = GetAppCodeFiles().ToList(); if (filesToCompile.Count == 0) { return(new CompatibilityCheckResult()); } var csCompiler = CSharpCodeProviderFactory.CreateCompiler(); var referencedAssemblies = new List <Assembly>(); var codeTypeDeclarations = new Dictionary <string, List <CodeTypeDeclaration> >(); foreach (var dataTypeDescriptor in DataMetaDataFacade.GeneratedTypeDataTypeDescriptors) { if (!includeDataTypeDescriptor && dataTypeDescriptor.DataTypeId == dataTypeDescriptorToTest.DataTypeId) { continue; } var dataTypeDescriptorToUse = dataTypeDescriptor; if (includeDataTypeDescriptor && dataTypeDescriptor.DataTypeId == dataTypeDescriptorToTest.DataTypeId) { dataTypeDescriptorToUse = dataTypeDescriptorToTest; } referencedAssemblies.AddRange(InterfaceCodeGenerator.GetReferencedAssemblies(dataTypeDescriptorToUse)); var codeTypeDeclaration = InterfaceCodeGenerator.CreateCodeTypeDeclaration(dataTypeDescriptorToUse); if (!codeTypeDeclarations.TryGetValue(dataTypeDescriptorToUse.Namespace, out var declarations)) { declarations = new List <CodeTypeDeclaration>(); codeTypeDeclarations.Add(dataTypeDescriptorToUse.Namespace, declarations); } declarations.Add(codeTypeDeclaration); var tempFilePath = GetTempFileName(dataTypeDescriptorToUse); filesToCompile.Add(tempFilePath); using (var file = File.Create(tempFilePath)) { using (var sw = new StreamWriter(file)) { var codeNamespace = new CodeNamespace(dataTypeDescriptorToUse.Namespace); codeNamespace.Types.Add(codeTypeDeclaration); csCompiler.GenerateCodeFromNamespace(codeNamespace, sw, new CodeGeneratorOptions()); } var sb = new StringBuilder(); using (var sw = new StringWriter(sb)) { csCompiler.GenerateCodeFromMember(codeTypeDeclaration, sw, new CodeGeneratorOptions()); } } } filesToCompile.Sort(); var compilerParameters = new CompilerParameters { GenerateExecutable = false, GenerateInMemory = true }; compilerParameters.ReferencedAssemblies.AddRangeIfNotContained(referencedAssemblies.Select(f => f.Location).ToArray()); compilerParameters.ReferencedAssemblies.AddRangeIfNotContained(CodeGenerationManager.CompiledAssemblies.Select(f => f.Location).ToArray()); compilerParameters.AddLoadedAssemblies(false); compilerParameters.AddAssemblyLocationsFromBin(); compilerParameters.AddCommonAssemblies(); compilerParameters.RemoveGeneratedAssemblies(); var codeCompileUnit = new CodeCompileUnit(); foreach (var kvp in codeTypeDeclarations) { var codeNamespace = new CodeNamespace(kvp.Key); codeNamespace.Types.AddRange(kvp.Value.ToArray()); codeCompileUnit.Namespaces.Add(codeNamespace); } var compiler = CSharpCodeProviderFactory.CreateCompiler(); var compileResult = compiler.CompileAssemblyFromFile(compilerParameters, filesToCompile.ToArray()); if (!compileResult.Errors.HasErrors) { return(new CompatibilityCheckResult()); } // Checking for a missing assembly error, if it is present, that means that App_Code check isn't applicable due to circular reference foreach (CompilerError error in compileResult.Errors) { if (error.ErrorNumber == "CS0012" && error.ErrorText.Contains("Composite.Generated")) { return(new CompatibilityCheckResult()); } } return(new CompatibilityCheckResult(compileResult)); }
/// <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) { var 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 = CSharpCodeProviderFactory.CreateCompiler(); var compileResult = compiler.CompileAssemblyFromDom(compilerParameters, codeCompileUnit); if (!compileResult.Errors.HasErrors) { var resultAssembly = compileResult.CompiledAssembly; AddCompiledAssembly(resultAssembly); var resultTypes = resultAssembly.GetTypes(); var t2 = Environment.TickCount; Log.LogVerbose(LogTitle, $"Compile '{codeGenerationBuilder.DebugLabel}' in {t2 - t1}ms"); Log.LogVerbose(LogTitle, $"Types from : {compilerParameters.OutputAssembly}"); foreach (var resultType in resultTypes) { _compiledTypesByFullName[resultType.FullName] = resultType; } return(resultTypes); } OutputSourceCodeOnError(compiler, codeCompileUnit); 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; } var 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()); }