mtrc
mtrc

Reputation: 1345

Including C# files when compiling programmatically from a string

I was previously exporting CodeDOM CompilationUnits to files, and then reading those files back in to compile them using a CSharpCodeProvider. Today I refactored the code so that the CodeDOM is exported to a String:

public static string compileToString(CodeCompileUnit cu){
        // Generate the code with the C# code provider.
        CSharpCodeProvider provider = new CSharpCodeProvider();

        using (StringWriter sw = new StringWriter())
        {
            IndentedTextWriter tw = new IndentedTextWriter(sw, "    ");

            // Generate source code using the code provider.
            provider.GenerateCodeFromCompileUnit(cu, tw,
                new CodeGeneratorOptions());

            tw.Close();

            return sw.ToString ();
        }   
    }

And then changed the compilation so that it uses CompileFromSource:

public static Assembly BuildAssemblyFromString(string code){
        Microsoft.CSharp.CSharpCodeProvider provider = 
           new CSharpCodeProvider();
        ICodeCompiler compiler = provider.CreateCompiler();
        CompilerParameters compilerparams = new CompilerParameters();
        compilerparams.GenerateExecutable = false;
        compilerparams.GenerateInMemory = true;

        compilerparams.CompilerOptions = "/nowarn:162";
        string[] files = new string[]{"TemplateAesthetic.cs"};

        CompilerResults results = 
           compiler.CompileAssemblyFromSource(compilerparams, code);
        if (results.Errors.HasErrors)
        {
            StringBuilder errors = new StringBuilder("Compiler Errors :\r\n");
            foreach (CompilerError error in results.Errors )
            {
                errors.AppendFormat("Line {0},{1}\t: {2}\n", 
                       error.Line, error.Column, error.ErrorText);
                Debug.Log (error.ErrorText);
            }
        }
        else
        {
            return results.CompiledAssembly;
        }
        return null;
    }

Thanks to Maarten for noticing: the problem is that I need to include a real file (TemplateAesthetic.cs) in the compilation process, but this compilation happens from a string. Can you do a mixed compilation in this way using CompileAssemblyFromSource?

Upvotes: 0

Views: 647

Answers (1)

Maarten
Maarten

Reputation: 22945

Initial answer:

As far as I can see, your variable string[] files is not used anywhere. Do they need to be added to the compiler parameters somewhere?

Update:

The method you are using actually accepts a params string[] sources which means you can give multiple strings to the method. So the solution would be to read the files from disk into memory (strings), and create an array with all sources, and give that array to the method.

Change this:

CompilerResults = compiler.CompileAssemblyFromSource(compilerparams, code);

To this:

var fileContents = files.Select(x => File.ReadAllText(x)).ToList();
fileContents.Add(code);
CompilerResults results = compiler.CompileAssemblyFromSource(
    compilerparams, 
    fileContents
);

Sorry, no time to test it.

Upvotes: 1

Related Questions