от строки к методу - PullRequest
       28

от строки к методу

2 голосов
/ 03 февраля 2011

Короткий вопрос, В .NET 4.0 есть способ взять строку, представляющую тело метода, и скомпилировать ее в Func / Action, или для этого есть библиотека?

Пояснение:

Мне нужно что-то, что не будет генерировать dll, оно должно быть полностью динамическим, что-то вроде eval () в javascript. Мне нужно преобразовать строку в Func / Action без создания DLL.

Ответы [ 3 ]

4 голосов
/ 03 февраля 2011

Вы можете использовать CSharpCodeProvider класс для компиляции исходного кода в сборку.

Например:

var compiler = new CSharpCodeProvider(new Dictionary<string, string> { { "CompilerVersion", "v4.0" } });
var options = new CompilerParameters { OutputAssembly = path);
var results = compiler.CompileAssemblyFromFile(options, sourceFile);

Чтобы скомпилировать одну функцию, выможет обернуть его в класс с соответствующими операторами using для создания полного исходного файла, а затем получить делегата, используя Reflection:

var assembly = results.CompiledAssembly;
var method = assembly.GetType("WrapperClassName").GetMethod("MethodName");
var delegate = (Action)Delegate.CreateDelegate(typeof(Action), method);

Для более полного примера :

static readonly Assembly[] References = new[] { typeof(Enumerable).Assembly, typeof(Component).Assembly };
public Action CompileMethodstring source) {
    var options = new CompilerParameters(References.Select(a => a.Location).ToArray()) {
        GenerateInMemory = true
    };
    string fullSource = @"public static class HolderClass { public static void Execute() { \r\n" + source + "\r\n} }";
    try {
        var compiler = new CSharpCodeProvider(new Dictionary<string, string> { { "CompilerVersion", "v4.0" } });

        var results = compiler.CompileAssemblyFromSource(options, fullSource);

        if (results.Errors.Count > 0)
            throw new InvalidOperationException(String.Join(
                Environment.NewLine, 
                results.Errors.Cast<CompilerError>().Select(ce => ce.ErrorText)
            ));

        return (Action)Delegate.CreateDelegate(
            typeof(Action),
            results.CompiledAssembly.GetType("HolderClass").GetMethod("Execute")
        );
    } finally { options.TempFiles.Delete(); }
}
1 голос
/ 12 февраля 2011

Вы также можете использовать CS-Script.Net Это встроенная платформа сценариев, которая также позволяет вам делать следующее:

dynamic script = CSScript.LoadCode(@"using System;
                                     public class Script
                                     {
                                         public void SayHello(string greeting)
                                         {
                                             Console.WriteLine(greeting);
                                         }
                                     }")
                                    .CreateObject("*");
script.SayHello("Hello World!");

Я использовал в производстве почти2 года, и это был отличный способ создавать настраиваемые приложения.У меня есть пример проекта , если вы заинтересованы.

0 голосов
/ 03 февраля 2011

CSharpCodeProvider может быть тем, что вы ищете. Однако вам нужно создать действительный код C # (то есть вам нужно создать класс для этого метода).

...