Search code examples
c#.netreflectionlambdaexpression-trees

Expression.Lamda is not working with dynamically generated class


Here is sample code do test:

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

Here I get an exception

Specified method is not supported

How can I avoid it? I don't have this type an compile-time, and I want to create a constructor by using Expressions instead of Emitting it manually. Is it even possible? I did it with instance methods, but I did it without using this. Now I need it, but access to type if forbidden while it is under construction.


Solution

  • Well, I found an elegant workaround for this.

    • Firstly, we just create a base class, in my case it was:

      public abstract class AsyncClientBase
      {
          protected readonly IAsyncRequestProcessor Processor;
      
          protected AsyncClientBase(IAsyncRequestProcessor processor)
          {
              Processor = processor;
          }
      }
      
    • Then we can use fields in our expressions (because base type is already builded).

    • Then we use Emit to create pass-params constructors (here is an example)
    • Finally, we just change type T of this parameter in methods on T's base type (there is an implicit conversion child -> base, so that's ok), and we are able to use fields in our generated methods.

    Here is a complete code (see ServiceClient, Helpers.XLambdaExpression, Helper.EmitHelper).