Get values ​​from a complex class using reflection

I have a class that is created and populated from an xml string, I simplified it, for example, for purposes:

[XmlRoot("Person")]
public sealed class Person
{
    [XmlElement("Name")]
    public string Name { get; set; }

    [XmlElement("Location")]
    public string Location { get; set; }

    [XmlElement("Emails", Type = typeof(PersonEmails)]
    public PersonEmails Emails { get; set; }
}

public class PersonEmails
{
    [XmlElement("Email", Type = typeof(PersonEmail))]
    public PersonEmail[] Emails { get; set; }
}

public class PersonEmail
{
    [XmlAttribute("Type")]
    public string Type { get; set; }

    [XmlText]
    public string Value { get; set; }
}

To extract the information, I try to load them into another class, which is simple:

public class TransferObject
{
    public string Name { get; set; }

    public ObjectField[] Fields { get; set; }
}

public class ObjectField
{
    public string Name { get; set; }
    public string Value { get; set; }
}

I just fill in the "Fields" from another object that would just be (Name = "Location", Value = "London"), but for email messages (Name = "Email" + Type, Value = jeff @ here.com)

Currently, I can fill out all the other fields, but I'm stuck in an email and know how to dig deep enough to be able to use reflection (or not) to get the information I need. I am currently using:

Person person = Person.FromXmlString(xmlString);
List<ObjectField> fields = new List<ObjectField>();
foreach (PropertyInfo pinfo in person.getType().GetProperties()
{
    fields.Add(new ObjectField { Name = pinfo.Name, Value = pinfo.getValue(person, null).ToString();
}

How can I expand the above to add all my letters to the list?

+4
2

, . :

class Program
{
    static void Main(string[] args)
    {
        Person person = new Person();
        person.Name = "Person One";
        person.Location = "India";
        person.Emails = new PersonEmails();
        person.Phones = new PersonPhones();
        person.Emails.Emails = new PersonEmail[] { new PersonEmail() { Type = "Official", Value = "xyz@official.com" }, new PersonEmail() { Type = "Personal", Value = "xyz@personal.com" } };
        person.Phones.Phones = new PersonPhone[] { new PersonPhone() { Type = "Official", Value = "789-456-1230" }, new PersonPhone() { Type = "Personal", Value = "123-456-7890" } };

        List<ObjectField> fields = new List<ObjectField>();

        fields = GetPropertyValues(person);

    }

    static List<ObjectField> GetPropertyValues(object obj)
    {
        List<ObjectField> propList = new List<ObjectField>();

        foreach (PropertyInfo pinfo in obj.GetType().GetProperties())
        {
            var value = pinfo.GetValue(obj, null);

            if (pinfo.PropertyType.IsArray)
            {
                var arr = value as object[];
                for (var i = 0; i < arr.Length; i++)
                {
                    if (arr[i].GetType().IsPrimitive)
                    {
                        propList.Add(new ObjectField() { Name = pinfo.Name + i.ToString(), Value = arr[i].ToString() });
                    }
                    else
                    {
                        var lst = GetPropertyValues(arr[i]);
                        if (lst != null && lst.Count > 0)
                            propList.AddRange(lst);
                    }
                }
            }
            else
            {
                if (pinfo.PropertyType.IsPrimitive || value.GetType() == typeof(string))
                {
                    propList.Add(new ObjectField() { Name = pinfo.Name, Value = value.ToString() });
                }
                else
                {
                    var lst = GetPropertyValues(value);
                    if (lst != null && lst.Count > 0)
                        propList.AddRange(lst);
                }
            }
        }
        return propList;
    }
}
+2

:

if(pinfo.PropertyType.IsArray)
{
  // Grab the actual instance of the array.
  // We'll have to use it in a few spots.
  var array = pinfo.GetValue(personObject);

  // Get the length of the array and build an indexArray.
  int length = (int)pinfo.PropertyType.GetProperty("Length").GetValue(array);

  // Get the "GetValue" method so we can extact the array values
  var getValue = findGetValue(pinfo.PropertyType);

  // Cycle through each index and use our "getValue" to fetch the value from the array.
  for(int i=0; i<length; i++)
    fields.Add(new ObjectField { Name = pinfo.Name, Value = getValue.Invoke(array, new object[]{i}).ToString();
}

// Looks for the "GetValue(int index)" MethodInfo.
private static System.Reflection.MethodInfo findGetValue(Type t)
{
  return (from mi in t.GetMethods()
    where mi.Name == "GetValue"
    let parms = mi.GetParameters()
    where parms.Length == 1
    from p in parms
    where p.ParameterType == typeof(int)
    select mi).First();
}

Reflection... , Type , (IsArray)... , Array GetValue(int index), .

Emails , . , . , , - Attribute:

static void fetchProperties(Object instance, List<ObjectField> fields)
{
  foreach(var pinfo in instance.GetType().GetProperties())
  {
    if(pinfo.PropertyType.IsArray)
    {
      ... // Code described above
    }
    else if(pinfo.PropertyType.GetCustomAttributes(typeof(SomeAttribute), false).Any())
      // Go the next level
      fetchProperties(pinfo.GetValue(instance), fields);
    else
    {
      ... // Do normal code
    }

  }
}
+1

All Articles