使用PropertyInfo.GetValue从嵌套类属性获取布尔值时触发TargetException异常的问题
问题根源分析
你遇到的TargetException是因为调用GetValue时传入的目标对象和PropertyInfo所属的类型不匹配。咱们拆解下你的代码逻辑:
你当前是链式获取多层PropertyInfo:
var info = settings.GetType().GetProperty(domain.ToUpper()) .PropertyType.GetProperty(settingsName) .PropertyType.GetProperty(deviceType);
最终的info是最内层Settings1/Settings2里RunOnClient/RunOnServer的PropertyInfo,但你却把最外层的settings对象传给了GetValue——这个属性根本不属于Settings类型,自然会抛出类型不匹配的异常。
正确思路是:每获取一层PropertyInfo后,先拿到该属性对应的对象实例,再用这个实例去获取下一层的属性。
修复后的代码
public bool IsDeviceOperable(ServiceType type, bool isServer, string domain) { string settingsFileContent = _fileReader.Read(_filePathProvider.GetSettingsFilePath()); var settings = _jsonDeserializer.Deserialize<Settings>(settingsFileContent); var settingsName = GetSettingsNameByType(type); string deviceType = GetDeviceType(isServer); // 第一步:获取Domain层级的实例(比如FirstDomain/SecondDomain) var domainProperty = settings.GetType().GetProperty(domain.ToUpper()); if (domainProperty == null) throw new ArgumentException($"Domain {domain} 不存在于Settings类中"); var domainInstance = domainProperty.GetValue(settings); if (domainInstance == null) throw new InvalidOperationException($"{domain} 对应的实例为null"); // 第二步:获取Settings层级的实例(比如Settings1/Settings2) var settingsProperty = domainProperty.PropertyType.GetProperty(settingsName); if (settingsProperty == null) throw new ArgumentException($"Settings {settingsName} 不存在于 {domainProperty.PropertyType.Name} 类中"); var settingsInstance = settingsProperty.GetValue(domainInstance); if (settingsInstance == null) throw new InvalidOperationException($"{settingsName} 对应的实例为null"); // 第三步:获取最终布尔属性并取值 var deviceProperty = settingsProperty.PropertyType.GetProperty(deviceType); if (deviceProperty == null) throw new ArgumentException($"设备属性 {deviceType} 不存在于 {settingsProperty.PropertyType.Name} 类中"); bool value = (bool)deviceProperty.GetValue(settingsInstance); return value; }
关键修改点说明
- 分层获取实例:不再直接链式获取
PropertyInfo,每一层都先通过GetValue拿到当前属性的对象实例,再基于这个实例去取下一层属性,确保目标对象和PropertyInfo类型匹配。 - 空值防御:增加了
PropertyInfo和实例的空值判断,避免NullReferenceException,同时抛出更明确的异常信息,方便调试定位问题。 - 类型匹配:最后调用
deviceProperty.GetValue(settingsInstance)时,settingsInstance是Settings1/Settings2的实例,和deviceProperty所属类型完全匹配,不会再触发类型不匹配异常。
额外优化建议
如果需要多次处理嵌套属性获取,或者层级可能变化,可以封装一个通用方法简化代码:
private object GetNestedPropertyValue(object obj, params string[] propertyNames) { foreach (var propName in propertyNames) { if (obj == null) return null; var prop = obj.GetType().GetProperty(propName); if (prop == null) return null; obj = prop.GetValue(obj); } return obj; }
之后你的方法可以简化为:
public bool IsDeviceOperable(ServiceType type, bool isServer, string domain) { string settingsFileContent = _fileReader.Read(_filePathProvider.GetSettingsFilePath()); var settings = _jsonDeserializer.Deserialize<Settings>(settingsFileContent); var settingsName = GetSettingsNameByType(type); string deviceType = GetDeviceType(isServer); var value = GetNestedPropertyValue(settings, domain.ToUpper(), settingsName, deviceType); return value != null && (bool)value; }
这个通用方法可以处理任意层级的嵌套属性获取,代码更简洁易维护。
内容的提问来源于stack exchange,提问作者dezox
相关产品推荐
相关产品推荐

