dimanche 23 décembre 2018

Reflection: Read List-type properties of an object, containing another object

I am trying to serialize nested objects using reflection. I am able to do this fine for properties containing a single value, but I am having trouble with list type properties that contain another class.

In the code sample below I have a class Dish which contains a list of of Recipe classes as a property, which itself contains a list of Step classes.

I am able to get the PropertyInfo of the List property, but when I try to get the contents of it by invoking the get method, I get a simple object back, not a List of e.g. Steps:

var listObjects =  property.GetGetMethod().Invoke(dish, null);

I managed to cast that into a List of objects like this:

List<object> listValues = ( listObjects as IEnumerable<object>).Cast<object>().ToList();

Now at least I can iterate over this List, but I cannot get the acutal properties of the original classes like the step description.

So I know the type of the List via property.PropertyType.GenericTypeArguments.First(), but its at runtime. I am thinking on how to perform a proper cast to transform my List<object> into a conrete type like List<Step>.

What I want to achieve: Serialize all property values of dish and all its attached Lists of objects.

I appreciate any ideas.

using System;
using System.Linq;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        var dish = new Dish(){
                 Recipes = new List<Recipe>(){
                           new Recipe(){
                               RecipeName = "Preparation", 
                               Steps = new List<Step>(){
                                       new Step(){
                                       Description = "Prepare Stuff",
                                       }
                               }
                           },
                           new Recipe(){
                           RecipeName = "Main Course",
                           Steps = new List<Step>(){
                                   new Step(){
                                      Description = "Do this",
                                   },
                                   new Step(){
                                      Description = "Then do that",
                                   }
                               }
                      }, }, };

        var serializer = new Serializer();
        serializer.SerializeDish(dish);
    }
}

public class Serializer
{
    public void SerializeDish(Dish dish)
    {
        var dishType = typeof (Dish);
        var listProps = dishType.GetProperties().Where(x => (x.PropertyType.IsGenericType && x.PropertyType.GetGenericTypeDefinition() == typeof (List<>)));
        foreach (var property in listProps)
        {
            var propertyGetMethod = property.GetGetMethod();
            var listObjects = propertyGetMethod.Invoke(dish, null);
            Console.WriteLine("Name:"+property.Name + " " + "List-Type:"+property.PropertyType.GenericTypeArguments.First());

            //Here its getting fuzzy
            List<object> listValues = ( listObjects as IEnumerable<object>).Cast<object>().ToList();
            foreach ( var item in listValues ) {
                Console.WriteLine(item);
            }
        }
    }
}

public class Dish
{
    public List<Recipe> Recipes {get;set;}
}

public class Recipe
{
    public string RecipeName{get;set;}
    public List<Step> Steps {get;set;}
}

public class Step
{
    public string Description {get;set;}
}





Aucun commentaire:

Enregistrer un commentaire