如何查找类型属性字段并实现指定属性制表符拼接的扩展方法
问题2:自定义扩展方法实现指定属性的制表符拼接
你想要的类似arr.Select(x => x.first, x.second, x.third).ToList()的写法,其实可以通过泛型扩展方法+表达式树实现,既能灵活指定属性,又能保持代码简洁。咱们来改造一下你的扩展方法:
实现自定义扩展方法
这个方法接受多个属性选择器表达式,解析出对应的属性后拼接值:
using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; public static class EnumerableTabExtensions { // 保留你原有的全属性拼接方法 public static IEnumerable<string> JoinByTab<T>(this IEnumerable<T> list) where T : class { if (list == null || !list.Any()) return Enumerable.Empty<string>(); var properties = list.First().GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); return list.Select(x => string.Join("\t", properties.Select(p => p.GetValue(x)?.ToString() ?? string.Empty))); } // 新增的指定属性拼接方法 public static IEnumerable<string> JoinSelectedByTab<T>(this IEnumerable<T> list, params Expression<Func<T, object>>[] propertySelectors) { // 边界判断,避免空引用 if (list == null || !list.Any() || propertySelectors == null || propertySelectors.Length == 0) return Enumerable.Empty<string>(); // 解析每个属性选择器,获取对应的PropertyInfo var targetProperties = propertySelectors.Select(selector => { // 处理值类型装箱的情况(比如int、decimal等属性会被包装成UnaryExpression) var memberExpr = selector.Body as MemberExpression; if (memberExpr == null) { var unaryExpr = selector.Body as UnaryExpression; memberExpr = unaryExpr?.Operand as MemberExpression; } if (memberExpr == null || !(memberExpr.Member is PropertyInfo prop)) throw new ArgumentException("请传入有效的属性选择器"); return prop; }).ToList(); // 遍历集合,拼接指定属性的值 return list.Select(item => string.Join("\t", targetProperties.Select(prop => prop.GetValue(item)?.ToString() ?? string.Empty))); } }
使用示例
用你提供的匿名类型集合测试:
string str = "1,2,3;2,3,4;4,5,6"; var arr = str .Split(';') .Select(x => x.Split(',')) .Select(x => new { first = x[0], second = x[1], third = x[2] }) .ToList(); // 调用扩展方法,得到你想要的结果 var result = arr.JoinSelectedByTab(x => x.first, x => x.second, x => x.third).ToList(); // result 就是 ["1\t2\t3", "2\t3\t4", "4\t5\t6"]
为什么这么写?
- 支持任意数量的属性选择,灵活度拉满
- 处理了值类型属性的装箱问题(比如int类型属性会自动装箱,这里做了兼容)
- 加入了null值判断,避免
NullReferenceException - 链式调用符合C#的LINQ风格,可读性强
内容的提问来源于stack exchange,提问作者Максим Попов
相关产品推荐
相关产品推荐

