score:4

Accepted answer

the cause of the problem in question is the line

currentparameter = expression.parameter(currenttype, currentparameter.name + "." + property.name);

inside visitnew method.

with your sample, it creates a new parameter called "x.sub", so if we mark the parameters with {}, the actual result is

sub = new subtype()
{
    id = {x.sub}.id
}, 

rather than expected

sub = new subtype()
{
    id = {x}.sub.id
},

in general you should not create new parameterexpressions except when remapping lambda expressions. and all newly created parameters should be passed to expression.lambda call, otherwise they will be considered "not defined".

also please note that the visitor code has some assumptions which doesn't hold in general. for instance

var xoriginal = expression.propertyorfield(currentparameter, x.name);

won't work inside nested new, because there you need access to a member of the x parameter like x.sub.id rather than x.id. which is basically the corersonding expression from newexpression.arguments.

processing nested lambda expressions or collection type members and linq methods with expression visitors requires much more state control. while converting simple nested anonymous new expression like in the sample does not even need a expressionvisitor, because it could easily be achieved with simple recursive method like this:

public static expression<func<tin, tout>> transform<tin, tout>(this expression<func<tin, object>> source)
{
    return expression.lambda<func<tin, tout>>(
        transform(source.body, typeof(tout)),
        source.parameters);
}

static expression transform(expression source, type type)
{
    if (source.type != type && source is newexpression newexpr && newexpr.members.count > 0)
    {
        return expression.memberinit(expression.new(type), newexpr.members
            .select(m => type.getproperty(m.name))
            .zip(newexpr.arguments, (m, e) => expression.bind(m, transform(e, m.propertytype))));
    }
    return source;
}

Related Query

More Query from same tag