【问题标题】:c# Recursive Reflection & Generic Lists setting default propertiesc# Recursive Reflection & Generic Lists 设置默认属性
【发布时间】:2011-02-08 10:15:50
【问题描述】:

我正在尝试使用反射来实现以下目标:

我需要一个方法,我传入一个对象,该方法将递归地用子对象实例化该对象,并使用默认值设置属性。我需要将整个对象实例化到所需的多个级别。

此方法需要能够处理具有多个属性的对象,这些属性将是其他对象的通用列表。

这是我的示例代码(当我得到一个包含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);
        }
    }
}

谢谢

【问题讨论】:

  • 这将有助于了解您在哪一行得到错误。此外,您似乎只是为类型名称包含 BusinessObjects 的属性创建新对象,不清楚这是否是您的意图。

标签: c# generics reflection recursion


【解决方案1】:

这是一个棘手的问题:)

当你向你的初始化器传递一个包含一些“BusinessObjects”类型的通用列表作为属性的对象时,这个属性将传递你的

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

表达式,因为实例化的泛型类型将具有如下名称:

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

这会导致使用 List 本身作为参数调用初始化方法。该列表将有一个名为 Item 的 SomeBusinessObjects 类型的索引器。这也将通过上述条件,因此您也将尝试对其进行初始化。结果是这样的:

obj.ListProperty.Item = new SomeBusinessObject();

而索引器只能在这样的初始化中使用

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

这表明,您确实缺少一个参数。

你要怎么做取决于你:)

【讨论】:

    【解决方案2】:

    您可以通过检查 property.PropertyType.IsGeneric 来过滤掉,这对于通用容器是正确的。如果需要,还请检查property.PropertyType.IsArray

    此外,您可能还希望避免使用非通用容器。在这种情况下,测试对象是否属于此类容器的接口类型。例如 - 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!
    }
    

    【讨论】:

    • 或者您可以只使用该语言的“is”运算符(为此目的而存在),并避免不必要的方法调用和相等比较。
    猜你喜欢
    • 2012-04-07
    • 2011-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多