如何从集合中的属性获取正确的nameof()结果?
获取嵌套属性名称的替代方案
嘿,我懂你的需求——你想让nameof()返回类似"Items.Sku"这样的嵌套属性路径,但可惜原生nameof()做不到这一点,它只能解析单个标识符,没办法处理order.Items.Sku这种链式访问的场景。不过我们可以用表达式树来实现这个功能,下面给你两种实用的解决方案:
方案1:通用表达式树解析方法(类型安全,推荐)
写一个通用工具方法,通过表达式树解析嵌套属性的完整路径,既能保留类型安全,又能自动获取正确的属性名:
public static string GetNestedPropertyName<T>(Expression<Func<T>> propertyExpression) { var memberExpr = propertyExpression.Body as MemberExpression; if (memberExpr == null) throw new ArgumentException("输入必须是属性访问的表达式"); var propertyNames = new List<string>(); // 从最内层属性往上遍历,收集所有属性名称 while (memberExpr != null) { propertyNames.Add(memberExpr.Member.Name); memberExpr = memberExpr.Expression as MemberExpression; } // 反转后拼接成完整路径 propertyNames.Reverse(); return string.Join(".", propertyNames); }
使用示例
因为Items是List<Item>,我们可以通过索引器(比如[0])代表集合中的元素,表达式树会自动解析到Sku属性:
Requires.That(order.Items.TrueForAll(x => !string.IsNullOrEmpty(x.Sku)), GetNestedPropertyName(() => order.Items[0].Sku), "Sku must contain a value");
这个方法返回的结果就是"Items.Sku",完全符合你的需求。而且如果后续修改了Item.Sku的名称,编译器会自动报错,避免硬编码带来的维护问题。
方案2:手动拼接nameof结果(简单但不够优雅)
如果你的场景比较简单,也可以直接手动拼接两个nameof的结果,虽然不够灵活,但胜在简单:
Requires.That(order.Items.TrueForAll(x => !string.IsNullOrEmpty(x.Sku)), $"{nameof(order.Items)}.{nameof(Item.Sku)}", "Sku must contain a value");
这种方式的缺点是,当属性名修改时,你需要确保两处nameof都同步更新,否则会出现不一致的情况。
内容的提问来源于stack exchange,提问作者PixelPaul
相关产品推荐
相关产品推荐

