You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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;
}
关键修改点说明
  1. 分层获取实例:不再直接链式获取PropertyInfo,每一层都先通过GetValue拿到当前属性的对象实例,再基于这个实例去取下一层属性,确保目标对象和PropertyInfo类型匹配。
  2. 空值防御:增加了PropertyInfo和实例的空值判断,避免NullReferenceException,同时抛出更明确的异常信息,方便调试定位问题。
  3. 类型匹配:最后调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 20:43:15