jeudi 22 juin 2023

C# and multi-level reflection

I have a very complex object for which I am trying to write validation methods. The information comes in, is serialized into the object and then I'm trying to do one of two things:

  1. Check if the required fields have data
  2. For those fields that have default values that can be used, if no value exists, set the field to the default value.

A simplified version of the JSON data looks as follows:

{
    "User": {
        "Name": "John Dude",
        "Department": "Sales"
    },
    
    "IDNumber": "23-0019872",
    "Addresses": [{
            "Street": "123 One St",
            "City": "Pittsville",
            "State": "CA",
            "Zip": "95432"
        },
        {
            "Street": "987 Dead End Dr",
            "City": "Nowhere",
            "State": "MI",
            "Zip": "45987"
        }
    ]
}

So my complex object has simple fields (string, int, bool, etc.), objects (User), and lists of objects (Addresses).

In my config file I have a list of data to check. So the various fields are either like .User or Addresses.Street. Nothing before the dot indicates the element is at the root and if it has something before the dot, it means that I have to check that object for a field.

I would think that checking the fields should be just a simple matter of using reflection. It doesn't matter what kind of object it is accessing, so long as the value is not null or empty, it is enough to pass this validation level (more specific checks will come later).

I'm able to check the first level fields (User, IDNumber, and Address) with the standard code.

if (messageData.GetType().GetProperty(FullField[1]).ToString() == null ||
    messageData.GetType().GetProperty(FullField[1]).ToString() == String.Empty) {
       wasFieldFound = false;
}

The problem comes when I'm trying to check the complex object fields or the list object fields.

var container = messageData.GetType().GetProperty(FullField[0]);
string ContainerName = container.Name;
string[] ListElements = 
     ConfigurationManager.AppSettings["ListFields"].ToString().Split('|');
bool isList = false;

foreach (string Element in ListElements) {
    if (ContainerName.Equals(Element))
       isList = true;
}

if (!isList) {
   if (container.GetType().GetProperty(FullField[1]).ToString() == null ||
       container.GetType().GetProperty(FullField[1]).ToString().Equals(String.Empty))
            wasFieldFound = false;
}

In the case where the item is just a complex object, the field I am checking is read into the string array FullField (so User.Name is split into FullField[0] = User and FullField[1] = Name). The variable container is getting the User element but the check on FullField[1] is null. I've thought about trying to cast the container to another variable of the correct type but I've not had any luck with that.

The short question is how do you get an object via reflextion and then access a field or property of that object via reflextion?





Aucun commentaire:

Enregistrer un commentaire