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();
        }
    }
Другие вопросы по тегам