【问题标题】:Roslyn - CodeDom: HowTo dynamically compile Code to Universal-Windows-LibraryRoslyn - CodeDom:如何将代码动态编译到 Universal-Windows-Library
【发布时间】:2015-10-15 08:08:47
【问题描述】:

我正在为 WPF 项目生成一个动态包含包装类的 .NET Dll。我正在使用 System.CodeDom.Compiler.CodeDomProvider 类。

现在我必须为 Universal-Windows-Dll 创建一个包装类。 由于System.CodeDom.Compiler.CodeDomProvider 类仍然使用旧的.NET 编译器,我不得不切换到新的Roslyn 编译器(通过添加Nuget 包Microsoft.CodeDom.Providers.DotNetCompilerPlatform)。 然后我用新的CSharpCodeProvider 替换了code-dom-Provider 的实例化。

new Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider();

代码编译得很好,但我找不到设置 TargetFramework / CompilerVersion 的方法。 旧的CodeDomProviderCompilerOptions,我可以在其中指定CompilerVersion 等。但是新的 Roslyn 没有这个选项(或者我很愚蠢地找到它)。

结果是将 DLL 编译为普通的 .NET 4.x Dll。但我需要一个 Universal-Windows Dll,因为它用于 Universal-Project。

浏览 Internet 我发现了许多使用 Roslyn 编译器的不同方法。它们中的大多数似乎来自编译器的旧 Beta 版本,因此它们都不起作用。 Roslyn.Compilers 命名空间(在大多数示例中使用)似乎是 beta 中的命名空间。

有人知道如何正确使用 roslyn 编译器吗? 我不想修改编译器。我只是想通过从 SourceCode 编译来动态生成 DLL,但我必须指定 Platform Target。

【问题讨论】:

    标签: c# dll win-universal-app roslyn codedom


    【解决方案1】:

    有一个选项可以引用编译器和运行时版本。 Roslyn 的最新版本有这个新特性,你可以指定你想要使用的目标框架和你想要使用的编译器版本。

    我也在四处寻找最新的 Roslyn 库来编译一个 CSharp6 版本的程序,以针对 4.6 框架进行编译。下面是我的工作示例。

    注意,runtimepath 变量指向 .Net 框架库和解析器中的 CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp6) 选项。

     public 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 Assemblies\Microsoft\Framework\.NETFramework\v4.6\{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.WindowsRuntimeApplication)
                        .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);
            }
    
            public static void Main(string[] args)
            {
                //ReferenceFinder finder = new ReferenceFinder();
                //finder.Find("Read");
    
                var fileToCompile = @"C:\Users\..\Documents\Visual Studio 2013\Projects\SignalR_Everything\Program.cs";
                var source = File.ReadAllText(fileToCompile);
                var parsedSyntaxTree = Parse(source, "", CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp6));
    
                var compilation
                    = CSharpCompilation.Create("Test.dll", new SyntaxTree[] { parsedSyntaxTree }, DefaultReferences, DefaultCompilationOptions);
                try
                {
                    var result = compilation.Emit(@"c:\temp\Test.dll");
    
                    Console.WriteLine(result.Success ? "Sucess!!" : "Failed");
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex);
                }
                Console.Read();
            }
        }
    

    【讨论】:

    • 我建议你使用 RuntimeEnvironment.GetRuntimeDirectory() 来避免硬编码运行时路径。
    • 我对此的评论是,它似乎不值得为 UWP 动态编译,因为 UWP 运行时环境不允许您动态加载程序集。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-04
    • 1970-01-01
    • 2021-01-29
    • 1970-01-01
    • 2011-12-12
    • 2010-10-26
    • 2019-03-14
    相关资源
    最近更新 更多