Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
180 views
in Technique[技术] by (71.8m points)

How to compile a C# file with Roslyn programmatically?

I read that you can't compile C# 6.0 with CSharpCodeProvider and therefor trying to do with with Roslyn. But I can't find a good example how to load a file and then compile it to a dll.

How should I write something similar to this code with Roslyn? Or is there some other way to do it? Now when I try to compile files that contain reference to projects with C# 6.0 code it just say "The type or namespace name 'x' does not exist in the namespace 'y' (are you missing an assembly reference?)"

    public string CompileCode()
    {
        var provider = new CSharpCodeProvider();
        var outputPath = Path.Combine(Path.GetDirectoryName(_path), $"Code.dll");
        var compilerparams = new CompilerParameters(_referencedAssemblies, outputPath);
        CompilerResults results = provider.CompileAssemblyFromFile(compilerparams, _path);
        var dllPath = results.PathToAssembly;
        if (!results.Errors.HasErrors)
            return dllPath;
        PrintError(results.Errors);
        return ""; 
    }

In summary I want to:

  • Load a C# file
  • Compile it to a dll so I can load it later.
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I have created a sample for you to work with. You need to tweak it to use the run time for .Net 4.6 so that CSharp6 version is availble to you. I have added little details so that you can choose the options of compilations.

Changes required - Change the path of runtime to target .Net 4.6 Change the LanguageVersion.Csharp5 to LanguageVersion.Csharp6 in below sample.

 class Program
    {
        private static readonly IEnumerable<string> DefaultNamespaces =
            new[]
            {
                "System", 
                "System.IO", 
                "System.Net", 
                "System.Linq", 
                "System.Text", 
                "System.Text.RegularExpressions", 
                "System.Collections.Generic"
            };

        private static string runtimePath = @"C:Program Files (x86)Reference AssembliesMicrosoftFramework.NETFrameworkv4.5.1{0}.dll";

        private static readonly IEnumerable<MetadataReference> DefaultReferences =
            new[]
            {
                MetadataReference.CreateFromFile(string.Format(runtimePath, "mscorlib")),
                MetadataReference.CreateFromFile(string.Format(runtimePath, "System")),
                MetadataReference.CreateFromFile(string.Format(runtimePath, "System.Core"))
            };

        private static readonly CSharpCompilationOptions DefaultCompilationOptions =
            new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
                    .WithOverflowChecks(true).WithOptimizationLevel(OptimizationLevel.Release)
                    .WithUsings(DefaultNamespaces);

        public static SyntaxTree Parse(string text, string filename = "", CSharpParseOptions options = null)
        {
            var stringText = SourceText.From(text, Encoding.UTF8);
            return SyntaxFactory.ParseSyntaxTree(stringText, options, filename);
        }

        static void Main(string[] args)
        {
            var fileToCompile = @"C:UsersDesktopHomeDocumentsVisual Studio 2013ProjectsConsoleForEverythingSignalR_EverythingProgram.cs";
            var source = File.ReadAllText(fileToCompile);
            var parsedSyntaxTree = Parse(source, "", CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp5));

            var compilation
                = CSharpCompilation.Create("Test.dll", new SyntaxTree[] { parsedSyntaxTree }, DefaultReferences, DefaultCompilationOptions);
            try
            {
                var result = compilation.Emit(@"c:empTest.dll");

                Console.WriteLine(result.Success ? "Sucess!!" : "Failed");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
            }
            Console.Read();
        }

This would need little tweaks but it should give you desired results. Change it as you may wish.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...