2010-04-15 80 views
3

我尝试使用反射来实现以下目标:C#回归反射和泛型列表设置默认属性

我需要一种方法在那里我传递一个对象,并且此方法将递归实例与子对象的对象,使用默认值设置属性。我需要根据需要将整个对象实例化为多个级别。

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

这里是我的示例代码(我收到的参数数量不匹配异常,当我得到含有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); 
     } 
    } 
} 

感谢

+0

这将有助于了解哪条线路出现错误。另外,它看起来像只为类型名称包含BusinessObjects的属性创建新对象,但不清楚这是否是您的意图。 – 2010-04-15 14:45:50

回答

0

这是一个棘手的:)

当您传递初始值设定项时,将包含一些“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]] 

这将导致初始化方法被调用列表本身作为参数。该列表将具有名为SomeBusinessObjects类型的项目的索引器。这也将通过上述条件,所以你也会尝试初始化它。它的结果是这样的:

obj.ListProperty.Item = new SomeBusinessObject(); 

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

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

这说明,的确,你缺少的参数。

什么,你打算怎么办,这是给你:)

+0

看到我的答案。 :) – Nayan 2010-04-15 15:07:44

1

您可以通过检查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! 
} 
+2

或者你可以只使用语言的“is”操作符(为此目的而存在),并避免不必要的方法调用和等式比较。 – 2010-08-28 10:08:16