/// <summary> /// Generates source code for the provided assembly. /// </summary> /// <param name="input"> /// The assembly to generate source for. /// </param> /// <returns> /// The generated source. /// </returns> public string GenerateSourceForAssembly(Assembly input) { if (input.GetCustomAttribute <GeneratedCodeAttribute>() != null || input.GetCustomAttribute <SkipCodeGenerationAttribute>() != null) { return(string.Empty); } var generated = this.GenerateCode(input, new[] { input }.ToList()); if (generated.Syntax == null) { return(string.Empty); } return(CodeGeneratorCommon.GenerateSourceCode(CodeGeneratorCommon.AddGeneratedCodeAttribute(generated))); }
/// <summary> /// Generates source code for the provided assembly. /// </summary> /// <param name="input"> /// The assembly to generate source for. /// </param> /// <returns> /// The generated source. /// </returns> public string GenerateSourceForAssembly(Assembly input) { if (!ShouldGenerateCodeForAssembly(input)) { return(string.Empty); } var generated = GenerateForAssemblies(new List <Assembly> { input }, false); if (generated.Syntax == null) { return(string.Empty); } return(CodeGeneratorCommon.GenerateSourceCode(CodeGeneratorCommon.AddGeneratedCodeAttribute(generated))); }
/// <summary> /// Generates source code for the provided assembly. /// </summary> /// <param name="input"> /// The assembly to generate source for. /// </param> /// <returns> /// The generated source. /// </returns> public string GenerateSourceForAssembly(Assembly input) { RegisterGeneratedCodeTargets(input); if (input.GetCustomAttribute <GeneratedCodeAttribute>() != null || input.GetCustomAttribute <SkipCodeGenerationAttribute>() != null) { return(string.Empty); } var generated = GenerateForAssemblies(new List <Assembly> { input }, false); if (generated.Syntax == null) { return(string.Empty); } return(CodeGeneratorCommon.GenerateSourceCode(CodeGeneratorCommon.AddGeneratedCodeAttribute(generated))); }
/// <summary> /// Generates and compiles an assembly for the provided syntax. /// </summary> /// <param name="generatedSyntax"> /// The generated code. /// </param> /// <param name="assemblyName"> /// The name for the generated assembly. /// </param> /// <param name="emitDebugSymbols"> /// Whether or not to emit debug symbols for the generated assembly. /// </param> /// <returns> /// The raw assembly. /// </returns> /// <exception cref="CodeGenerationException"> /// An error occurred generating code. /// </exception> private Assembly CompileAssembly(GeneratedSyntax generatedSyntax, string assemblyName, bool emitDebugSymbols) { // Add the generated code attribute. var code = CodeGeneratorCommon.AddGeneratedCodeAttribute(generatedSyntax); // Reference everything which can be referenced. var assemblies = AppDomain.CurrentDomain.GetAssemblies() .Where(asm => !asm.IsDynamic && !string.IsNullOrWhiteSpace(asm.Location)) .Select(asm => MetadataReference.CreateFromFile(asm.Location)) .Cast <MetadataReference>() .ToArray(); // Generate the code. var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary); #if NETSTANDARD2_0 // CoreFX bug https://github.com/dotnet/corefx/issues/5540 // to workaround it, we are calling internal WithTopLevelBinderFlags(BinderFlags.IgnoreCorLibraryDuplicatedTypes) // TODO: this API will be public in the future releases of Roslyn. // This work is tracked in https://github.com/dotnet/roslyn/issues/5855 // Once it's public, we should replace the internal reflection API call by the public one. var method = typeof(CSharpCompilationOptions).GetMethod("WithTopLevelBinderFlags", BindingFlags.NonPublic | BindingFlags.Instance); // we need to pass BinderFlags.IgnoreCorLibraryDuplicatedTypes, but it's an internal class // http://source.roslyn.io/#Microsoft.CodeAnalysis.CSharp/Binder/BinderFlags.cs,00f268571bb66b73 options = (CSharpCompilationOptions)method.Invoke(options, new object[] { 1u << 26 }); #endif string source = null; if (this.logger.IsEnabled(LogLevel.Debug)) { source = CodeGeneratorCommon.GenerateSourceCode(code); // Compile the code and load the generated assembly. this.logger.Debug( ErrorCode.CodeGenSourceGenerated, "Generating assembly {0} with source:\n{1}", assemblyName, source); } var compilation = CSharpCompilation.Create(assemblyName) .AddSyntaxTrees(code.SyntaxTree) .AddReferences(assemblies) .WithOptions(options); using (var outputStream = new MemoryStream()) { var emitOptions = new EmitOptions() .WithEmitMetadataOnly(false) .WithIncludePrivateMembers(true); if (emitDebugSymbols) { emitOptions = emitOptions.WithDebugInformationFormat(DebugInformationFormat.Embedded); } var compilationResult = compilation.Emit(outputStream, options: emitOptions); if (!compilationResult.Success) { source = source ?? CodeGeneratorCommon.GenerateSourceCode(code); var errors = string.Join("\n", compilationResult.Diagnostics.Select(_ => _.ToString())); this.logger.Warn( ErrorCode.CodeGenCompilationFailed, "Compilation of assembly {0} failed with errors:\n{1}\nGenerated Source Code:\n{2}", assemblyName, errors, source); throw new CodeGenerationException(errors); } this.logger.Debug( ErrorCode.CodeGenCompilationSucceeded, "Compilation of assembly {0} succeeded.", assemblyName); return(Assembly.Load(outputStream.ToArray())); } }