Подтвердить что ты не робот

Как скомпилировать С# файл с Roslyn программно?

Я читал, что вы не можете скомпилировать С# 6.0 с CSharpCodeProvider и поэтому пытаетесь сделать это с Roslyn. Но я не могу найти хороший пример, как загрузить файл, а затем скомпилировать его в dll.

Как мне написать что-то похожее на этот код с Roslyn? Или есть другой способ сделать это? Теперь, когда я пытаюсь скомпилировать файлы, содержащие ссылку на проекты с кодом С# 6.0, он просто говорит: "Тип или имя пространства имен" x "не существует в пространстве имен" y "(вам не хватает ссылки на сборку?)"

    public string CompileCode()
    {
        var provider = new CSharpCodeProvider();
        var outputPath = Path.Combine(Path.GetDirectoryName(_path), $"Code.dll");
        var compilerparams = new CompilerParameters(_referencedAssemblies, outputPath);
        CompilerResults results = provider.CompileAssemblyFromFile(compilerparams, _path);
        var dllPath = results.PathToAssembly;
        if (!results.Errors.HasErrors)
            return dllPath;
        PrintError(results.Errors);
        return ""; 
    }

В заключение я хочу:

  • Загрузите файл С#
  • Скомпилируйте его в dll, чтобы я мог загрузить его позже.
4b9b3361

Ответ 1

Я создал образец для вас. Вам нужно настроить его, чтобы использовать время выполнения для .Net 4.6, чтобы версия CSharp6 была доступна для вас. Я добавил немного подробностей, чтобы вы могли выбирать варианты компиляции.

Необходимые изменения - Измените путь выполнения к целевому .Net 4.6 Измените LanguageVersion.Csharp5 на LanguageVersion.Csharp6 в следующем примере.

 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.5.1\{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.DynamicallyLinkedLibrary)
                    .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);
        }

        static void Main(string[] args)
        {
            var fileToCompile = @"C:\Users\DesktopHome\Documents\Visual Studio 2013\Projects\ConsoleForEverything\SignalR_Everything\Program.cs";
            var source = File.ReadAllText(fileToCompile);
            var parsedSyntaxTree = Parse(source, "", CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp5));

            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();
        }

Это потребует небольших настроек, но оно должно дать вам желаемые результаты. Измените его, как вы пожелаете.

Ответ 2

Вы должны использовать пакет NuGet Microsoft.CodeAnalysis.CSharp.

var syntaxTree = CSharpSyntaxTree.ParseText(source);

CSharpCompilation compilation = CSharpCompilation.Create(
    "assemblyName",
    new[] { syntaxTree },
    new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) },
    new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

using (var dllStream = new MemoryStream())
using (var pdbStream = new MemoryStream())
{
    var emitResult = compilation.Emit(dllStream, pdbStream);
    if (!emitResult.Success)
    {
        // emitResult.Diagnostics
    }
}