The problem is that the expression you're creating looks quite different from the one that's normally created from a lambda that returns an anonymous type.
In your case, the body of the expression looks like this:
- MemberInit
- New
- Parameters: empty
- Members: empty
- Bindings:
- Binding: LfdVtgNr = Param_0.LfdVtgNr
- New
But it should look like this:
- New
- Parameters: Param_0.LfdVtgNr
- Members: LfdVtgNr
(Don't let the syntax fool you, creating anonymous type is really converted to just a constructor call, not MemberInit.)
But to make this work, the generated type has to contain such constructor (though it doesn't actually have to do anything). Also, the generated type doesn't have to be generic, so you can remove all code related to gaBuilders
.
The important part of the code will now look like this:
foreach (var field in fields)
typeBuilder.DefineField(field.Key, field.Value, FieldAttributes.Public);
var parameters = fields.ToArray();
var ctor = typeBuilder.DefineConstructor(
MethodAttributes.Public, CallingConventions.Standard,
parameters.Select(p => p.Value).ToArray());
var ctorIl = ctor.GetILGenerator();
ctorIl.Emit(OpCodes.Ret);
for (int i = 0; i < parameters.Length; i++)
{
ctor.DefineParameter(i + 1, ParameterAttributes.None, parameters[i].Key);
}
builtTypes[className] = typeBuilder.CreateType();
With this, you can now change the code that creates the expression to something like:
var ci = dynamicType.GetConstructors().Single();
var selector =
Expression.Lambda(
Expression.New(
ci,
ci.GetParameters()
.Select(
p => Expression.Property(
paramEx, dictIndex.Values.Single(x => x.Name == p.Name))),
ci.GetParameters().Select(p => dynamicType.GetField(p.Name))),
paramEx);