Variable 'x.Sub' of type 'SubType' referenced from scope '' but it is not defined error

淺唱寂寞╮ 提交于 2019-12-01 08:37:10

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;
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!