C#中如何使用字符串变量构建限定类名并访问对应属性
实现方案
你明确知晓所有嵌套类结构的前提下,优先使用编译时安全的委托映射方案,避免反射的性能损耗和运行时风险。
方案1:委托字典映射(最推荐)
提前把属性名对应的读写逻辑存在字典中,循环时直接调用即可,执行效率和硬编码完全一致,且编译时会做类型校验。
// 1. 提前定义映射,仅需初始化一次,注意替换代码中的GeographiesType、CensusReturnType为你实际的类名 private static readonly Dictionary<string, Func<GeographiesType, string>> _geoValueGetter = new() { ["CensusBlocks"] = geo => geo.CensusBlocks[0].BLOCK, ["_111thCongressionalDistricts"] = geo => geo._111thCongressionalDistricts[0].BLOCK, ["CensusTracts"] = geo => geo.CensusTracts[0].BLOCK, ["Counties"] = geo => geo.Counties[0].BLOCK, ["StateLegislativeDistrictsLower"] = geo => geo.StateLegislativeDistrictsLower[0].BLOCK, ["StateLegislativeDistrictsUpper"] = geo => geo.StateLegislativeDistrictsUpper[0].BLOCK, ["CountySubdivisions"] = geo => geo.CountySubdivisions[0].BLOCK, ["States"] = geo => geo.States[0].BLOCK }; private static readonly Dictionary<string, Action<CensusReturnType, string>> _censusValueSetter = new() { ["CensusBlocks"] = (cr, val) => cr.CensusBlocks.Name = val, ["_111thCongressionalDistricts"] = (cr, val) => cr._111thCongressionalDistricts.Name = val, ["CensusTracts"] = (cr, val) => cr.CensusTracts.Name = val, ["Counties"] = (cr, val) => cr.Counties.Name = val, ["StateLegislativeDistrictsLower"] = (cr, val) => cr.StateLegislativeDistrictsLower.Name = val, ["StateLegislativeDistrictsUpper"] = (cr, val) => cr.StateLegislativeDistrictsUpper.Name = val, ["CountySubdivisions"] = (cr, val) => cr.CountySubdivisions.Name = val, ["States"] = (cr, val) => cr.States.Name = val }; // 2. 循环逻辑实现 string[] items = { "CensusBlocks", "_111thCongressionalDistricts", "CensusTracts", "Counties", "StateLegislativeDistrictsLower", "StateLegislativeDistrictsUpper", "CountySubdivisions", "States" }; var geographies = records.result.addressMatches[0].geographies; foreach (var item in items) { var blockValue = _geoValueGetter[item](geographies); _censusValueSetter[item](censusreturn, blockValue); }
方案2:动态类型访问(适合快速开发场景)
如果不想写映射代码,可使用dynamic关键字绕过编译时类型检查,适合属性结构不稳定、临时开发的场景,缺点是编译时不会校验属性正确性,运行时出错概率更高:
string[] items = { "CensusBlocks", "_111thCongressionalDistricts", "CensusTracts", "Counties", "StateLegislativeDistrictsLower", "StateLegislativeDistrictsUpper", "CountySubdivisions", "States" }; dynamic geoDynamic = records.result.addressMatches[0].geographies; dynamic censusDynamic = censusreturn; foreach (var item in items) { // 注意:如果是强类型类,该写法实际底层仍会调用反射,性能低于方案1 var blockValue = geoDynamic.GetType().GetProperty(item).GetValue(geoDynamic)[0].BLOCK; var censusProp = censusDynamic.GetType().GetProperty(item).GetValue(censusDynamic); censusProp.GetType().GetProperty("Name").SetValue(censusProp, blockValue); }
如果你的geographies和censusreturn是JSON反序列化得到的JObject类对象,可以直接用索引访问,写法更简洁:
foreach (var item in items) { var blockValue = geographies[item][0]["BLOCK"].ToString(); censusreturn[item]["Name"] = blockValue; }
内容的提问来源于stack exchange,提问作者John Miller
相关产品推荐
相关产品推荐

