开发者

c# Recursive Reflection & Generic Lists setting default properties

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<AnotherSetObje开发者_如何转开发cts>:

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


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!
}


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 :)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜