C # динамический компилятор, получить стандартный вывод при компиляции в памяти - PullRequest
0 голосов
/ 02 января 2019

Я хочу получить стандартный динамически скомпилированный код.

Мой код:

using System;
using System.Collections.Generic;
using System.Reflection;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.IO;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            var source = File.ReadAllText("form.cs");

        Dictionary<string, string> providerOptions = new Dictionary<string, string>
                {
                    {"CompilerVersion", "v4.0"}
                };
            CSharpCodeProvider provider = new CSharpCodeProvider(providerOptions);

            CompilerParameters compilerParams = new CompilerParameters
            {
                GenerateInMemory = true,
                GenerateExecutable = false,
                ReferencedAssemblies =  {"System.dll" ,"mscorlib.dll"}
        };
            CompilerResults results = provider.CompileAssemblyFromSource(compilerParams, source);
            Assembly assembly = results.CompiledAssembly;
            Type program = assembly.GetType("program.TestPerson");
            MethodInfo main = program.GetMethod("Main");
            var outp= main.Invoke(null, null);
            //Console.WriteLine(outp);
            Console.ReadLine();
        }
    }
}

Содержимое form.cs:

using System;
namespace program {
    public class TestPerson
    {
         public static void Main()
        {
            var person1 = new Person();
            Console.WriteLine(person1.Name);
        }
    }
}

public class Person
{
    public Person()
    {
        Name = "unknown";
    }
        public Person(string name)
        {
            Name = name;
        }
        public string Name { get;set; }
        public override string ToString()
        {
            return Name;
        }
    }

ЧтоЯ точно хочу иметь стандартный вывод form.cs (Console.WriteLine) после компиляции в переменной в родительском приложении, кстати, я НЕ хочу встраивать код в файл и запускать его как процесс и читать его вывод,Также предположим, что содержимое form.cs НЕ доступно для редактирования.

1 Ответ

0 голосов
/ 02 января 2019

Возможно, что main сбило вас с толку, но, как я написал в своем комментарии, ваш динамически скомпилированный код не запускается в своем собственном процессе (это также может быть достигнуто, но это намного сложнее), поэтому он делаетне имеет собственного выхода.Метод main - это просто еще один метод в другом классе в вашем домене приложений по умолчанию в текущем процессе.Это означает, что он запишет на консоль вашего внешнего хостинга процесса.Вы должны захватить этот вывод с помощью Console.SetOut.Смотрите следующий фрагмент linqpad:

string source = @"using System;
namespace program {
    public class TestPerson
    {
        public static void Main()
        {
            Console.WriteLine(""TEST"");
        }
    }
}";

void Main()
{
    Dictionary<string, string> providerOptions = new Dictionary<string, string>
            {
                {"CompilerVersion", "v4.0"}
            };
    CSharpCodeProvider provider = new CSharpCodeProvider(providerOptions);

    CompilerParameters compilerParams = new CompilerParameters
    {
        GenerateInMemory = true,
        GenerateExecutable = false,
        ReferencedAssemblies = { "System.dll", "mscorlib.dll" }
    };
    CompilerResults results = provider.CompileAssemblyFromSource(compilerParams, source);
    Assembly assembly = results.CompiledAssembly;
    Type program = assembly.GetType("program.TestPerson");
    MethodInfo main = program.GetMethod("Main");

    var sb = new StringBuilder();
    var writer = new StringWriter(sb);
    Console.SetOut(writer);

    var outp = main.Invoke(null, null);

    sb.ToString().Dump(); // this Dump is from linqpad, do what you want with the StringBuilder content 

    Console.ReadLine();
 }

Если вы хотите записать в исходный стандартный вывод, сначала сохраните его, например, так:

...
var oldOut = Console.Out;
Console.SetOut(writer);

var outp = main.Invoke(null, null);

oldOut.WriteLine($"The result is: {sb.ToString()}");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...