使用反射将通用列表的实例添加到对象

时间:2012-08-28 15:50:52

标签: c# generics reflection

我正在尝试使用反射将通用列表附加到类的实例,与附加简单对象方法不同,PropertyInfo.SetValue(obj, value, index)在值为{{"Parameter count mismatch."}时返回异常List<SomeType> 1}}(而不是字符串,int,bool甚至是自定义类)。

那个夏天可能没什么意义;以下内容可能有助于解释我的目的。

假设我们尝试使用反射填充以下类:

public class Foo
{

 public virtual int someInt {get; set;}
 public virtual IList<SomeClass> list {get; set;}

}

该方法可能如下所示:

public static T Parse<T>(HttpRequest request) where T : new()
{
   returnObj = new T();
   PropertyInfo[] properties = typeof(T).GetProperties();
   foreach (PropertyInfo p in properties)
   {
     // Get a meaningful property name
     string ins = System.Text.RegularExpressions.Regex.Replace(p.PropertyType.FullName, "([^,]*),.*$", "$1");
     switch(ins)
     {
        // populate int
        case "System.Int32":
           p.SetValue(returnObj, Int32.Parse(request[p.Name]) , null);
           break;



        // populate list
        case "System.Collections.Generic.IList`1[[SomeNamespace.Domain.SomeClass":
           IList<SomeClass> list = new List<SomeClass>();
           foreach (string s in request[p.Name].Split(','))
           {
              list.Add(new SomeClass(s));
           }
           // This will throw the exception 'Parameter count mismatch.'
           p.SetValue(returnObj, list, null);
           break;
      }
   }
   return returnObj;
}

但是,当尝试以这种方式添加List(IList)的实例时,会抛出异常。

编辑:澄清一下,如果用精细梳齿(断点)完成此方法(那么,应用程序中的那个,不完全是这个)并且所有变量都按预期填充;直到SetValue抛出异常;如果有人需要更多信息,请询问。

Edit2:所以我构建了一个较小的应用程序来测试它(以上传为例);我在重建自己的问题时遇到了麻烦;正如你们许多人所说的那样有效。当我设法跟踪它时,我会用这个问题更新这个问题。它可能是微不足道的,因为这些事情经常是(原始的代码库很大,因此不适合我发布)。到目前为止,感谢您的帮助,并为浪费您的时间而道歉。

2 个答案:

答案 0 :(得分:2)

我正在运行您的问题中的代码并进行一些小的更改以使其编译并且它似乎工作正常:

void Main()
{
    Parse<Foo>();
}

public static T Parse<T>() where T : new()
{
   var returnObj = new T();
   PropertyInfo[] properties = typeof(T).GetProperties();
   foreach (PropertyInfo p in properties)
   {
     // Get a meaningful property name
     string ins = p.PropertyType.Name;
     switch(ins)
     {
        // populate int
        case "Int32":
           p.SetValue(returnObj, 1 , null);
           break;

        // populate list
        case "IList`1":
           var list = new List<string>();
           // This will throw the exception 'Parameter count mismatch.'
           p.SetValue(returnObj, list, null);
           break;
      }
   }
   return returnObj;
}

public class Foo
{
 public virtual int someInt {get; set;}
 public virtual IList<string> list {get; set;}
}

如果您将Foo更改为具有返回IList的索引器属性,则会在您的问题中出现例外情况:

public class Foo
{
 public virtual int someInt {get; set;}
 public virtual IList<string> this[int key] 
 {
    get{ return null; }
    set 
    {
    }
 }
}

生成:

  

TargetParameterCountException:参数计数不匹配。

答案 1 :(得分:1)

您是否已确认案例

"System.Collections.Generic.IList`1[[SomeNamespace.Domain.SomeClass"

被击中?当我传入List时,即使是作为IList创建的List,GetType()也会给我

System.Collections.Generic.List`1[SomeNamespace.Domain.SomeClass]

使用它可能更可靠:

typeOf(System.Collections.Generic.IList).isAssignableFrom(p.GetType())