2016-07-15 3 views
0

Вот пример кода сделать тест:Expression.Lamda не работает с динамически сгенерированного класса

var assembly = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("asm"), AssemblyBuilderAccess.Run); 
var builder = assembly.DefineDynamicModule("MainModule"); 
Type type = builder.DefineType("newType"); 
var parameter = Expression.Parameter(type); 
Console.WriteLine(type); 
var expr = Expression.Lambda(Expression.Constant(1), parameter); 

Здесь я получаю исключение

Указанный метод не поддерживается

Как могу ли я избежать этого? У меня нет такого типа времени компиляции, и я хочу создать конструктор, используя Expression s вместо того, чтобы испускать его вручную. Возможно ли это? Я сделал это с помощью методов экземпляра, но я сделал это без использования this. Теперь мне это нужно, но доступ к типу, если он запрещен, пока он строится.

+0

Вам не хватает 'var finalType = builder.CreateType();' Посмотрите на мой вопрос [здесь] (http://stackoverflow.com/questions/38389479/reflection-emit-throws-badimageformatexception/38389729?noredirect = 1 # comment64189813_38389729) – lokusking

+0

Это не окончательный тип. Как я могу добавить конструктор после того, как я заморожу класс? –

+0

После того, как вы определили свой новый класс, вы должны создать его, чтобы получить допустимый тип. Если вы хотите добавить другого конструктора, сделайте что-то вроде этого: builder.DefineConstructor (MethodAttributes.Public, CallingConventions.HasThis, new [] {typeof (string)}); 'No overload принимает выражение – lokusking

ответ

1

Ну, я нашел изящное обходное решение для этого.

  • Во-первых, мы просто создать базовый класс, в моем случае это было:

    public abstract class AsyncClientBase 
    { 
        protected readonly IAsyncRequestProcessor Processor; 
    
        protected AsyncClientBase(IAsyncRequestProcessor processor) 
        { 
         Processor = processor; 
        } 
    } 
    
  • Тогда мы можем использовать поля в наших выражениях (так как базовый тип уже построен).

  • Затем мы используем Emit, чтобы создать проход-Params конструкторами (here пример)
  • Наконец, мы просто изменить тип T из this параметра в методах на базовом типе T «s (есть неявное ребенок преобразования - > base, так что это нормально), и мы можем использовать поля в наших сгенерированных методах.

Here полный код (см ServiceClient, Helpers.XLambdaExpression, Helper.EmitHelper).