Roslyn - CodeDom: как динамически скомпилировать код в Universal-Windows-Library
Я генерирую.NET Dll, динамически содержащие классы-оболочки для проекта WPF. Я делаю это с помощью класса System.CodeDom.Compiler.CodeDomProvider.
Теперь мне нужно создать класс-оболочку для Universal-Windows-Dll. Так как System.CodeDom.Compiler.CodeDomProvider
класс по-прежнему использует старый компилятор.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.
Просматривая Интернет, я нашел много разных способов использования Roslyn Compiler. Большинство из них, похоже, из старых бета-версий компилятора, поэтому ни одна из них не работает. Roslyn.Compilers
Пространство имен (которое использовалось в большинстве примеров) кажется пространством имен из бета-версий.
Кто-нибудь знает, как правильно использовать компилятор Roslyn? Я не хочу изменять компилятор. Я просто хочу динамически сгенерировать DLL, скомпилировав ее из SourceCode, но я должен указать Platform Target.
1 ответ
Есть возможность ссылаться на компилятор и версию во время выполнения. В последнем выпуске Roslyn есть эта новая функция, с помощью которой вы можете указать, какую целевую платформу вы хотите использовать и какую версию компилятора вы хотите использовать.
Я также искал новую библиотеку Roslyn, чтобы скомпилировать версию программы CSharp6 для компиляции на платформе 4.6. Ниже мой рабочий образец.
Заметка, runtimepath
переменная, которая указывает на библиотеки.Net Framework и 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();
}
}