1

我有的:

public class ClassA: Class C
{
    public string Prop1 {get;set;}
    public ClassB Prop2 {get; set;}
}

public class ClassB: Class C
{
    public int Prop3 {get; set;}
}

我想要一个像 nameof() 这样的方法,它的行为如下:

string myString = GetPropertyName(ClassA.Prop2.Prop3);

我的字符串:

"ClassB\Prop2\Prop3"

public string GetPropertyName(<no idea what the parameter type should be>)
{
    I cant still fiqure out how to get the full name and how to put / in between, but what to put 
    as parameter so that I can put the properties as parameters like we do in name of?
}
4

2 回答 2

1

如果不考虑性能,您可以尝试查看表达式树。起点将是这样的:

public static string GetPropertyPath<T, TProp>(Expression<Func<T, TProp>> expr)
{
    var pathParts = new List<string>();
    var body = expr.Body;
    var cont = true;
    while(cont)
    {
        switch(body)
        {
            case MemberExpression me:
                body = me.Expression;
                pathParts.Add(me.Member.Name);
                break;
            case ParameterExpression pe: 
                cont = false;
                pathParts.Add(pe.Type.Name);
                break;
            default: body.Dump(); throw new InvalidOperationException();
        }
    }
    
    pathParts.Reverse();
    return string.Join("\\", pathParts);
} 

Console.WriteLine(GetPropertyName((ClassA x) => x.Prop2.Prop3)); // prints ClassA\Prop2\Prop3

这可以改进,但这个解决方案有很多缺点 - 一些编译时安全性丢失(见例外),性能(虽然你可以尝试缓存一些结果,但它是单独的难题,它仍然不会接近nameof)。另一种选择是研究 IL 编织(例如使用Fody),但不确定您可以在哪里使用它。

于 2020-07-03T11:49:50.680 回答
0

您可以使用MemberExpression. 基于此答案,您可以通过扩展方法的形式对您的情况进行小幅调整

public static class PropertyExtensions
{
    public static string GetPropertyFullPath<T, R>(this T obj, Expression<Func<T, R>> expression)
    {
        var buffer = new List<string>();
        var memberExpresiion = expression.Body as MemberExpression;
        while (memberExpresiion != null)
        {
            buffer.Add(memberExpresiion.Member.Name);
            if (memberExpresiion.Expression as MemberExpression == null)
            {
                buffer.Add(memberExpresiion.Member.DeclaringType.Name);
                break;
            }
            memberExpresiion = memberExpresiion.Expression as MemberExpression;
        }
        buffer.Reverse();
        return string.Join('/', buffer);
    }
}

用法:

        var t = new D();
        Console.WriteLine(t.GetPropertyFullPath(_ => _.Top.Deep.Deeper.VeryDeep));
于 2020-07-03T12:16:29.463 回答