Как сохранить дерево выражений в качестве основной точки входа в новый исполняемый файл на диске?

Я пытаюсь экспортировать дерево выражений в сборку PE в качестве основной точки входа. Я получил лямбда-выражение, построив дерево выражений, например:

using System.Linq;
using System;

// 1. use expression trees to create a block expression (not shown)

// 2. create a lambda expression: 
LambdaExpression exprLambda = Expression.Lambda(exprBlock, new ParameterExpression[0]);

MethodBuilder mbuilder = null;
// 3. ??? Somehow get a method builder instance that works ??? 

// 4. Compile the lambda using the MethodBuilder instance. 
exprLambda.CompileToMethod(mbuilder);

// 5. ??? Somehow get an AssemblyBuilder instance to .Save(..) this to disk.  ??? 

Шаги 3 и 5 - это то, чего мне не хватает.


person John K    schedule 01.03.2013    source источник
comment
Надеюсь, PE-файл должен означать сборку. Вместо этого используйте CompileToMethod().   -  person Hans Passant    schedule 02.03.2013
comment
@HansPassant, вы правы, PE-файл, содержащий IL.   -  person John K    schedule 02.03.2013
comment
Разве класс DynamicAssembly не позволяет вам устанавливать точку входа во время построения?   -  person JerKimball    schedule 02.03.2013


Ответы (1)


Вместо простого использования Expression.Compile используйте Expression.CompileToMethod(MethodBuilder).

Короткий, но полный пример, который создает исполняемый файл на диске с деревом выражений в качестве кода, выполняемого в точке входа:

using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Linq.Expressions;

class Program
{
    static void Main()
    {
        var asmName = new AssemblyName("Foo");
        var asmBuilder = AssemblyBuilder.DefineDynamicAssembly
            (asmName, AssemblyBuilderAccess.RunAndSave);
        var moduleBuilder = asmBuilder.DefineDynamicModule("Foo", "Foo.exe");

        var typeBuilder = moduleBuilder.DefineType("Program", TypeAttributes.Public);
        var methodBuilder = typeBuilder.DefineMethod("Main",
            MethodAttributes.Static, typeof(void), new[] { typeof(string) });

        Expression<Action> action = () => Console.WriteLine("Executed!");

        action.CompileToMethod(methodBuilder);

        typeBuilder.CreateType();
        asmBuilder.SetEntryPoint(methodBuilder);
        asmBuilder.Save("Foo.exe");
    }
}
person Jon Skeet    schedule 01.03.2013
comment
Это сработало отлично, спасибо! Я использовал свой экземпляр LambdaExpression вместо вашего action. - person John K; 02.03.2013