如何不使用反射,根据字符串列表匹配属性值填充FruitData列表
无需反射实现动态属性匹配赋值的几种方案
嘿,我完全理解你不想用反射的想法——反射不仅在性能上有额外开销,代码的可读性和维护性也不如强类型实现。针对你的场景,这里有几个实用的替代方案,都是强类型、编译时安全的:
方案1:字典映射(最灵活,适合属性较多或需动态扩展的场景)
我们可以提前构建一个字典,将fruits数组中的字符串与fruitDetails对应的属性获取逻辑关联起来。循环时直接通过字典键取值即可:
// 提前定义属性映射:键是fruits数组中的字符串,值是获取对应属性的委托 var propertyLookup = new Dictionary<string, Func<FruitModel, object>> { ["Color"] = model => model.Color, ["Price"] = model => model.Price, ["Shape "] = model => model.Shape, // 注意:你的数组里"Shape"后面有个空格,必须完全匹配 ["Nutrients"] = model => model.Nutrients }; foreach (var item in fruits) { var fruitData = new FruitData(); fruitData.Category = fruitDetails?.Category; // 尝试从字典中获取属性获取逻辑 if (propertyLookup.TryGetValue(item, out var getPropertyValue) && fruitDetails != null) { fruitData.Description = getPropertyValue(fruitDetails)?.ToString(); } fruitList.Add(fruitData); }
这个方案的优势在于扩展性强:后续新增属性时,只需在字典中添加一行即可,无需修改循环逻辑,且全程是强类型调用,没有反射的弊端。
方案2:Switch表达式(C# 8.0+,最简洁易读)
如果你的项目使用C# 8.0及以上版本,switch表达式是最直观的选择——代码简洁,且所有匹配逻辑都是编译时检查,避免运行时拼写错误:
foreach (var item in fruits) { var fruitData = new FruitData(); fruitData.Category = fruitDetails?.Category; // 使用switch表达式匹配属性 fruitData.Description = fruitDetails switch { null => null, // 处理fruitDetails为null的情况 _ => item switch { "Color" => fruitDetails.Color?.ToString(), "Price" => fruitDetails.Price?.ToString(), "Shape " => fruitDetails.Shape?.ToString(), "Nutrients" => fruitDetails.Nutrients?.ToString(), _ => null // 处理未匹配到的item值 } }; fruitList.Add(fruitData); }
这种写法逻辑一目了然,适合属性数量不多、逻辑固定的场景。
方案3:值元组列表映射(适合不习惯使用委托的场景)
如果对委托不太熟悉,也可以用值元组列表来存储属性映射关系,本质和字典方案类似:
// 先将fruitDetails的属性转换为键值对列表 var detailProperties = new List<(string Key, object Value)> { ("Color", fruitDetails?.Color), ("Price", fruitDetails?.Price), ("Shape ", fruitDetails?.Shape), ("Nutrients", fruitDetails?.Nutrients) }; foreach (var item in fruits) { var fruitData = new FruitData(); fruitData.Category = fruitDetails?.Category; // 查找匹配的键值对 var matchedProperty = detailProperties.FirstOrDefault(p => p.Key == item); fruitData.Description = matchedProperty.Value?.ToString(); fruitList.Add(fruitData); }
重要提示
注意你定义的fruits数组中,"Shape "后面带有一个空格——无论使用哪种方案,都要保证匹配的键与数组中的字符串完全一致,否则会出现匹配失败的情况!
内容的提问来源于stack exchange,提问作者The_Outsider




