2015-10-15 79 views
3

我正在生成一个动态包含WPF项目的包装类的.NET Dll。我正在用System.CodeDom.Compiler.CodeDomProvider类来完成它。Roslyn - CodeDom:HowTo动态编译代码到Universal-Windows-Library

现在我必须为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等。但新的罗斯林没有这个选项(或者我愚蠢地找到它)。

结果是它将DLL编译为一个正常的.NET 4.x Dll。但是我需要一个Universal-Windows Dll,因为它在Universal-Project中使用。

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

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

回答

3

有一个引用编译器和运行时版本的选项。最新版本的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(); 
     } 
    } 
+1

我建议您使用RuntimeEnvironment.GetRuntimeDirectory()来避免硬编码运行时路径。 –

+0

我对此的评论是,它似乎不值得为UWP动态编译,因为UWP运行时环境不会允许您动态加载程序集。 –