简体   繁体   English

c#递归反射和通用列表设置默认属性

[英]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<AnotherSetObjects> : 这是我的示例代码(当我得到一个包含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 谢谢

You can filter out by checking for property.PropertyType.IsGeneric which is true for generic containers. 您可以通过检查property.PropertyType.IsGeneric来筛选出来,这对于通用容器是真的。 If you need, also check for property.PropertyType.IsArray . 如果需要,还要检查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 . 例如 - 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 当您将包含某些“BusinessObjects”类型的通用列表的对象作为属性传递给初始化程序时,此属性将通过您的属性

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. 这导致使用List本身作为参数调用初始化方法。 The list will have an indexer named Item of type SomeBusinessObjects. 该列表将有一个名为Item的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 :) 你要做的就是取决于你:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM