C# - 如何获取复合对象的属性名称?

标签 c# asp.net .net

我有一个 Company 类,它有一个复合对象作为属性,它有公司对象作为其属性,等等。我需要用最少的代码获取最深层次的属性名称。

下面是这个案例的伪代码:

class Company
{
    public Person Boss
    {
        public Document CV
        {
             public string Title;
        }
    }
}

我需要用尽可能少的代码获得 "Company.Boss.CV.Title" 的字符串结果。这样做的天真方法是尝试 nameof(Company.Boss.CV.Title) 但正如我们所知,这只会产生“Title”。

我需要使用类型而不是纯字符串来允许编译器在有人更改属性名称时抛出错误。 显然是这样的:

string.Join('.', nameof(Company), nameof(Company.Boss), nameof(Company.Boss.CV), nameof(Company.Boss.CV.Title))

将在 100% 的时间内正常工作,但样板代码太多。非常感谢任何建议!

最佳答案

您可以使用表达式并将其分解,例如:

Expression<Func<Company, object>> myExpr = (c) => c.Boss.CV.Title;

var expr = myExpr.Body;
var sb = new StringBuilder();

// Traverse the expression
while (expr != null)
{
    switch (expr.NodeType){
        case ExpressionType.MemberAccess:
            var memberExpr = ((MemberExpression)expr);
            sb.Insert(0, "." + memberExpr.Member.Name, 1);
            expr = memberExpr.Expression;
            break;
        case ExpressionType.Parameter:
            var paramExpr = ((ParameterExpression)expr);
            parts.Add(paramExpr.Type.Name);
            sb.Insert(0, paramExpr.Type.Name, 1);
            expr = null;
            break;
        default:
            expr = null;
            break;
    }
}

var propertyPath = sb.ToString(); // "Company.Boss.CV.Title"

使用 ExpressionVisitor

实现自定义 ExpressionVisitor 有助于代码的清晰度。

public class MyExpressionVisitor : ExpressionVisitor{
    private List<string> parts;

    protected override Expression VisitMember(MemberExpression node)
    {
        parts.Add(node.Member.Name);
        return base.VisitMember(node);
    }

    protected override Expression VisitParameter(ParameterExpression node)
    {
        parts.Add(node.Type.Name);
        return base.VisitParameter(node);
    }

    public string GetPath(Expression e)
    {
        parts = new List<string>();
        Visit(e is LambdaExpression ? ((LambdaExpression)e).Body : e);
        parts.Reverse();
        return string.Join(".", parts);
    }
}

然后你可以调用它

Expression<Func<Company, object>> myExpr = (c) => c.Boss.CV.Title;
var myVisitor = new MyExpressionVisitor();
var propertyPath = myVisitor.GetPath(myExpr);

关于C# - 如何获取复合对象的属性名称?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57755486/

相关文章:

c# - 寻找更优雅的 DO WHILE 解决方案

c# - '域名/机器名 $' being used for authentication instead of ' 域名/用户名'

c# - 如何将中间件添加到.net 6中的worker项目中?

c# - 从 FileStream 获取原始路径

c# - 保护条款不触发

c# - 在 c# webservice 中读取发布的 XML 文件

c# - 如何用c#解压MSZIP文件?

asp.net - web-api 和 swagger 文档

asp.net - ASP.NET Windows身份验证不起作用/不接受凭据

c# - .NET 的明显单例实现?