MemberExpression.ToString-替换参数

问题描述

使用此方法:

public static string GetMemberIdentifier<TProp>(Expression<Func<Team,TProp>> expression)
{
    return expression.Body.ToString();
}

lambda表达式可以转换为字符串表示形式:

var nameIdentifier1 = GetMemberIdentifier(t => t.Members[1].Name);

给出(a):

t.Members.get_Item(1).Name

但是用以下方式调用它:

var i = 0;
var nameIdentifier2 = GetMemberIdentifier(t => t.Members[i].Name);

得出(b):

t.Members.get_Item(value(Program+<>c__DisplayClass2).i).Name

是否可以使b)中的输出与a)中的输出相同?

.NET小提琴:https://dotnetfiddle.net/cHG7H3

所需用法(简化):

for(int i = 0; i < team.Members.Count; i++)
{
    Console.WriteLine(GetMemberIdentifier(t => t.Members[i].Name));
}

输出:

t.Members.get_Item(0).Name
t.Members.get_Item(1).Name
t.Members.get_Item(2).Name

解决方法

如果您的lambda变得如此简单,则可以执行以下操作:

public class ArgumentsTransformToConstantVisitor : ExpressionVisitor
{
    private readonly Dictionary<string,Func<object>> args;

    public ArgumentsTransformToConstantVisitor(params (string varname,Func<object> resolver)[] args)
    {
        this.args = args.ToDictionary(i => i.varname,i => i.resolver);
    }
    
    protected override Expression VisitMember(MemberExpression node)
    {
        if (node.Expression is ConstantExpression && this.args.TryGetValue(node.Member.Name,out Func<object> resolver))
            return Expression.Constant(resolver());
        
        return base.VisitMember(node);
    }

    public string GetMemberIdentifier<TProp>(Expression<Func<Team,TProp>> expression)
    {
        return ((LambdaExpression)this.Visit(expression)).ToString();
    }
}
int i = 0;

var visitor = new ArgumentsTransformToConstantVisitor(("i",() => i));

for (i = 0; i < 5; i++)
{
    Console.WriteLine(visitor.GetMemberIdentifier(t => t.Members[i].Name));
}           

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...