C#循环内按属性名取类属性值 有无无需每次反射的高性能方案?
优化方案:缓存属性访问委托避免循环内重复反射
核心逻辑:仅在首次遇到指定属性名时做一次元数据查询、委托构建,后续所有调用直接复用缓存的取值委托,循环内无任何反射开销,性能接近硬编码取值。
方案1:通用动态缓存方案(支持任意新增字段/属性,无需修改业务代码)
首先定义线程安全的静态缓存,同属性名全局复用委托:
using System.Collections.Concurrent; using System.Linq.Expressions; using System.Reflection; public class YourServiceClass { // 缓存键:属性/字段名,缓存值:从Product实例取对应值的强类型委托 private static readonly ConcurrentDictionary<string, Func<Product, string>> _productValueGetterCache = new ConcurrentDictionary<string, Func<Product, string>>(); public void SetCopyProperty(List<Product> products, string propertyName) { // 缓存中不存在则自动构建委托,存在直接取 var getValue = _productValueGetterCache.GetOrAdd(propertyName, name => { // 适配字段、属性两种成员类型 MemberInfo member = typeof(Product).GetField(name); member ??= typeof(Product).GetProperty(name); if (member == null) { throw new ArgumentException($"Product类型中不存在名为{name}的公共字段/属性", nameof(propertyName)); } // 表达式树构建取值委托 var instanceParam = Expression.Parameter(typeof(Product), "instance"); var memberAccess = Expression.MakeMemberAccess(instanceParam, member); return Expression.Lambda<Func<Product, string>>(memberAccess, instanceParam).Compile(); }); // 循环内直接调用委托,无反射开销 foreach (var product in products) { product.Copy = getValue(product); } } }
如果是.NET 5+环境,可以替换表达式树部分为官方封装的CreateGetter方法,代码更简洁:
// 替换表达式树构建部分即可 if (member is FieldInfo field) { return (Func<Product, string>)field.CreateGetter<Product>(); } else if (member is PropertyInfo prop) { return (Func<Product, string>)prop.CreateGetter<Product>(); }
方案2:固定属性枚举方案(性能最高,适用于属性不会频繁新增的场景)
如果取值的字段是固定的几个(当前场景下只有Title、Description两个可选),可以直接用开关表达式硬编码委托,连首次构建委托的开销都完全消除:
public void SetCopyProperty(List<Product> products, string propertyName) { Func<Product, string> getValue = propertyName switch { nameof(Product.Title) => p => p.Title, nameof(Product.Description) => p => p.Description, _ => throw new ArgumentException($"不支持的属性名{propertyName}", nameof(propertyName)) }; foreach (var product in products) { product.Copy = getValue(product); } }
内容的提问来源于stack exchange,提问作者Dev Adekunle
相关产品推荐
相关产品推荐

