Roslyn - CodeDom:如何将代码动态编译为 Universal-Windows-Library
Roslyn - CodeDom: HowTo dynamically compile Code to Universal-Windows-Library
我正在为 WPF 项目生成动态包含包装器 classes 的 .NET Dll。我正在使用 System.CodeDom.Compiler.CodeDomProvider class.
现在我必须为 Universal-Windows-Dll 创建一个包装器 class。
由于 System.CodeDom.Compiler.CodeDomProvider
class 仍然使用旧的 .NET 编译器,我不得不切换到新的 Roslyn 编译器(通过添加 Nuget 包 Microsoft.CodeDom.Providers.DotNetCompilerPlatform
)。
然后我用新的 CSharpCodeProvider
.
替换了 code-dom-Provider 的实例化
new Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider();
代码编译正常,但我发现无法设置 TargetFramework/CompilerVersion。
旧的 CodeDomProvider
有 CompilerOptions
,我可以在其中指定 CompilerVersion
等。但是新的Roslyn没有这个选项(或者是我太笨才找到的)。
结果是它将 DLL 编译为普通的 .NET 4.x Dll。但我需要一个 Universal-Windows Dll,因为它用于 Universal-Project。
浏览 Internet 我发现了很多使用 Roslyn 编译器的不同方法。它们中的大多数似乎来自编译器的旧 Beta 版本,因此 none 它们可以工作。
Roslyn.Compilers
命名空间(在大多数示例中使用)似乎是来自测试版的命名空间。
有人知道如何正确使用 roslyn 编译器吗?
我不想修改编译器。我只是想通过从源代码编译动态生成一个 DLL,但我必须指定平台目标。
有一个选项可以引用编译器和运行时版本。最新版本的 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();
}
}
我正在为 WPF 项目生成动态包含包装器 classes 的 .NET Dll。我正在使用 System.CodeDom.Compiler.CodeDomProvider class.
现在我必须为 Universal-Windows-Dll 创建一个包装器 class。
由于 System.CodeDom.Compiler.CodeDomProvider
class 仍然使用旧的 .NET 编译器,我不得不切换到新的 Roslyn 编译器(通过添加 Nuget 包 Microsoft.CodeDom.Providers.DotNetCompilerPlatform
)。
然后我用新的 CSharpCodeProvider
.
new Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider();
代码编译正常,但我发现无法设置 TargetFramework/CompilerVersion。
旧的 CodeDomProvider
有 CompilerOptions
,我可以在其中指定 CompilerVersion
等。但是新的Roslyn没有这个选项(或者是我太笨才找到的)。
结果是它将 DLL 编译为普通的 .NET 4.x Dll。但我需要一个 Universal-Windows Dll,因为它用于 Universal-Project。
浏览 Internet 我发现了很多使用 Roslyn 编译器的不同方法。它们中的大多数似乎来自编译器的旧 Beta 版本,因此 none 它们可以工作。
Roslyn.Compilers
命名空间(在大多数示例中使用)似乎是来自测试版的命名空间。
有人知道如何正确使用 roslyn 编译器吗? 我不想修改编译器。我只是想通过从源代码编译动态生成一个 DLL,但我必须指定平台目标。
有一个选项可以引用编译器和运行时版本。最新版本的 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();
}
}