c# Recursive Reflection & Generic Lists setting default properties

为君一笑 提交于 2020-01-02 06:54:12

问题


I am trying to to use reflection to achieve the following:

I need a method where i pass in an object and this method will recursively instantiate the object with child objects and set the properties with default values. I need the entire object instantiated going as many levels as needed.

this method needs to be able to handle an object with a multiple properties that will be generic lists of other objects.

Here is my sample code (I am getting a parameter count mismatch exception when i get an object containing a List<AnotherSetObjects>:

private void SetPropertyValues(object obj)
{
    PropertyInfo[] properties = obj.GetType().GetProperties();

    foreach (PropertyInfo property in properties)
    {
        if (property.PropertyType.IsClass && property.PropertyType != typeof(string) && property.PropertyType.FullName.Contains("BusinessObjects"))
        {
            Type propType = property.PropertyType;

            var subObject = Activator.CreateInstance(propType);
            SetPropertyValues(subObject);
            property.SetValue(obj, subObject, null);
        }
        else if (property.PropertyType == typeof(string))
        {
            property.SetValue(obj, property.Name, null);
        }
        else if (property.PropertyType == typeof(DateTime))
        {
            property.SetValue(obj, DateTime.Today, null);
        }
        else if (property.PropertyType == typeof(int))
        {
            property.SetValue(obj, 0, null);
        }
        else if (property.PropertyType == typeof(decimal))
        {
            property.SetValue(obj, 0, null);
        }
    }
}

Thanks


回答1:


You can filter out by checking for property.PropertyType.IsGeneric which is true for generic containers. If you need, also check for property.PropertyType.IsArray.

Moreover, you may also want to avoid non-generic containers. In that case, test for object to be of interface types of such containers. Eg - IList.

bool isList(object data)
{
    System.Collections.IList list = data as System.Collections.IList;
    return list != null;
}

...
if (isList(obj)) {
    //do stuff that take special care of object which is a List
    //It will be true for generic type lists too!
}



回答2:


This is a tricky one :)

When you pass your initializer an object containing a generic list of some "BusinessObjects" type as a property, then this property will pass your

if (property.PropertyType.IsClass && property.PropertyType != typeof(string) && property.PropertyType.FullName.Contains("BusinessObjects"))

expression, because the instantiated generic type will have a name like this:

System.Collections.Generic.List`1[[ConsoleApplication92.XXXBusinessObjects, ConsoleApplication92, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]

This results in the initializer method being called with the List itself as a parameter. The list will have an indexer named Item of type SomeBusinessObjects. This will too pass the above condition so you'll try to initialize it too. It results is something like this:

obj.ListProperty.Item = new SomeBusinessObject();

whereas an indexer could only be used in an initialization like this

obj.ListProperty[0] = new SomeBusinessObject();

This shows, that indeed, your are missing a parameter.

What you gonna do about this is up to you :)



来源:https://stackoverflow.com/questions/2646224/c-sharp-recursive-reflection-generic-lists-setting-default-properties

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!