Search code examples
c#reflectionnestedpropertyinfo

Get the boolean value from nested classes property


I am trying to use the GetValue() method of PropertyInfo, but it seems like its not working.

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 info = settings.GetType().GetProperty(domain.ToUpper())
        .PropertyType.GetProperty(settingsName)
        .PropertyType.GetProperty(deviceType);


    bool value = (bool)info.GetValue(settings, null);

    return value;
}

It throws

System.Reflection.TargetException: 'Object does not match target type.'

My Settings file looks like this:

public class Settings
{
    public FirstDomain First { get; set; }
    public SecondDomain Second { get; set; }
    ...
}

Domain classes looks like this:

public class FirstDomain
{
    public Settings1 firstSettings { get; set; }
    public Settings2 secondSettings { get; set; }
    ...
}

public class SecondDomain
{
    public Settings1 firstSettings { get; set; }
    public Settings2 secondSettings { get; set; }
    ...
}

Settings classes look like this:

public class Settings1
{
    public bool RunOnClient { get; set; }
    public bool RunOnServer { get; set; }
}

public class Settings2
{
    public bool RunOnClient { get; set; }
    public bool RunOnServer { get; set; }
}

There is a reason for First Domain Second domain, and also the settings differ from each other, just for easier understanding, I renamed them.


Solution

  • The problem is that the code creates the property info for a nested property, but provides an instance of the parent object. The property info always operates on an instance of the type that the property is defined on.

    Therefore, you have to get the parent instances first and then call the property on the correct instance:

    var settings = _jsonDeserializer.Deserialize<Settings>(settingsFileContent);
    var settingsName = GetSettingsNameByType(type);
    
    string deviceType = GetDeviceType(isServer);
    
    var domainProp = settings.GetType().GetProperty(domain.ToUpper());
    var domainInst = domainProp.GetValue(settings, null);
    var settingsProp = domainProp
        .PropertyType.GetProperty(settingsName);
    var settingsInst = settingsProp.GetValue(domainInst, null);
    var deviceTypeProp = settingsProp
        .PropertyType.GetProperty(deviceType);
    
    bool value = (bool)deviceTypeProp.GetValue(settingsInst, null);