lundi 10 juin 2019

How to use reflection to access nested objects in elegant way?

I am getting some data from api, which is dynamic, and I would like to use reflection to strongly type this data for reuse in my app. I have three level hierarchy of object.

I would like to use reflection to combine specific properties that are of same type into collection.

Having following classes:

Level 1:

public sealed class DynamicData
{
    [JsonProperty(propertyName: "PersonInfo")]
    public DynamicDataPersonInfo PersonInfo { get; set; }

    [JsonProperty(propertyName: "Location")]
    public DynamicDataLocation Location { get; set; }
}

Level 2:

public sealed class DynamicDataPersonInfo
{
    [JsonProperty("title")]
    public string Title { get; set; }

    [JsonProperty("type")]
    public string Type { get; set; }

    [JsonProperty("properties")]
    public DynamicDataPersonInfoProperties Properties { get; set; }

    [JsonProperty("required")]
    public string[] PersonInfoRequired { get; set; }
}

public sealed class DynamicDataLocation
{
    [JsonProperty(propertyName: "title")]
    public string Title { get; set; }

    [JsonProperty(propertyName: "type")]
    public string Type { get; set; }

    [JsonProperty(propertyName: "properties")]
    public DynamicDataLocationProperties Properties { get; set; }

    [JsonProperty(propertyName: "required")]
    public string[] LocationRequired { get; set; }
}

Level 3:

public sealed class DynamicDataLocationProperties
{
    [JsonProperty(propertyName: "BuildingNumber")]
    public DynamicDataFieldInfo BuildingNumber { get; set; }

    [JsonProperty(propertyName: "UnitNumber")]
    public DynamicDataFieldInfo UnitNumber { get; set; }

    [JsonProperty(propertyName: "StreetName")]
    public DynamicDataFieldInfo StreetName { get; set; }

    [JsonProperty(propertyName: "StreetType")]
    public DynamicDataFieldInfo StreetType { get; set; }

    [JsonProperty(propertyName: "City")]
    public DynamicDataFieldInfo City { get; set; }

    [JsonProperty(propertyName: "StateProvinceCode")]
    public DynamicDataFieldInfo StateProvinceCode { get; set; }

    [JsonProperty(propertyName: "PostalCode")]
    public DynamicDataFieldInfo PostalCode { get; set; }
}

public sealed class DynamicDataPersonInfoProperties
{
    [JsonProperty(propertyName: "FirstGivenName")]
    public DynamicDataFieldInfo FirstGivenName { get; set; }

    [JsonProperty(propertyName: "MiddleName")]
    public DynamicDataFieldInfo MiddleName { get; set; }

    [JsonProperty(propertyName: "FirstSurName")]
    public DynamicDataFieldInfo FirstSurName { get; set; }

    [JsonProperty(propertyName: "DayOfBirth")]
    public DynamicDataFieldInfo DayOfBirth { get; set; }

    [JsonProperty(propertyName: "MonthOfBirth")]
    public DynamicDataFieldInfo MonthOfBirth { get; set; }

    [JsonProperty(propertyName: "YearOfBirth")]
    public DynamicDataFieldInfo YearOfBirth { get; set; }
}

Final level:

public sealed class DynamicDataFieldInfo
{
    [JsonProperty(propertyName: "type")]
    public string Type { get; set; }

    [JsonProperty(propertyName: "description")]
    public string Description { get; set; }

    [JsonProperty(propertyName: "label")]
    public string Label { get; set; }
}

I am attempting to make this generic as possible, and using reflection, but for each level I am using foreach loop. You know where this is going, and code looks terrible in my opinion:

private IReadOnlyList<DynamicProperty> CombineProperties(DynamicData deserializedRawData)
{
    List<DynamicProperty> combinedDynamicProperties = new List<DynamicProperty>();

    // dynamic data
    foreach (PropertyInfo propertiyofDynamicData in deserializedRawData.GetType()
        .GetProperties())
    {
        // dynamic data lower level
        foreach (PropertyInfo propertyOfDynamicDataMember in propertiyofDynamicData.GetType()
            .GetProperties()
            .Where(predicate: x => x.Name == "Properties"))
        {
            foreach (PropertyInfo propertyOfFieldInfo in propertyOfDynamicDataMember.GetType()
                .GetProperties())
            {
                DynamicDataFieldInfo dynamicDataFieldInfo = propertyOfFieldInfo.GetValue(propertyOfDynamicDataMember) as DynamicDataFieldInfo;
                combinedDynamicProperties.Add(new DynamicProperty {DynamicDataFieldInfo = dynamicDataFieldInfo, GroupType = FormHelper.GetFormGroupType(propertiyofDynamicData.Name)});
            }
        }
    }

    return combinedDynamicProperties;
}

Is there a way I can avoid this horrible looping?





Aucun commentaire:

Enregistrer un commentaire