无法在C#中使用Reflection强制转换列表

时间:2010-04-09 16:04:00

标签: c# .net xml reflection

目前我在C#中遇到很多问题。我正在编写的应用程序允许用户使用配置文件修改某些对象的属性。我希望能够将对象模型(用户项目)保存到XML。下面的函数在foreach循环的中间调用,循环遍历包含项目中所有其他对象的对象列表。我们的想法是,它可以递归地将对象模型转换为XML。

不要担心对“虚幻”的调用,只要它们包含某些单词,就会略微修改对象的名称。

      private void ReflectToXML(object anObject, XmlElement parentElement)
  {
     Type aType = anObject.GetType();
     XmlElement anXmlElement = m_xml.CreateElement(Unreal(aType.Name));
     parentElement.AppendChild(anXmlElement);
     PropertyInfo[] pinfos = aType.GetProperties();
     //loop through this objects public attributes
     foreach (PropertyInfo aInfo in pinfos)
     {
        //if the attribute is a list
        Type propertyType = aInfo.PropertyType;
        if ((propertyType.IsGenericType)&&(propertyType.GetGenericTypeDefinition() == typeof(List<>)))
        {
           List<object> listObjects = (aInfo.GetValue(anObject,null) as List<object>);
           foreach (object aListObject in listObjects)
           {
              ReflectToXML(aListObject, anXmlElement);
           }
        }
        //attribute is not a list
        else
           anXmlElement.SetAttribute(aInfo.Name, "");
     }
  }

如果对象属性只是字符串,那么应该将它们作为XML中的字符串属性写出来。如果一个对象属性是列表,那么它应该递归地调用“ReflectToXML”作为参数传递自己,从而创建我需要的嵌套结构,很好地反映了内存中的对象模型。

我遇到的问题是行

List<object> listObjects = (aInfo.GetValue(anObject,null) as List<object>);

强制转换不起作用,只返回null。 调试时我将行改为

object temp = aInfo.GetValue(anObject,null);

在它上面打了一个断点,看看“GetValue”正在返回什么。它返回一个“通用的对象列表”当然我应该能够投射它?令人烦恼的是temp变成了一个通用的对象列表但是因为我将temp声明为一个单个对象,所以我无法遍历它,因为它没有Enumerator。

当我只将它作为类的propertyInfo时,如何遍历对象列表?

我知道在这一点上我只会保存一个空字符串列表,但那很好。我很高兴看到结构现在省去了。

提前致谢

4 个答案:

答案 0 :(得分:5)

我假设实际值不是List<object>,而是List<string>List<int>或其他类型 > object

如果是这样,那么演员表失败的原因是因为泛型类既不是共同的也不是逆变的。

但是,在C#4.0中,您可以通过转换为foreach来使IEnumerable<object>循环工作,因为接口可以是共同/逆变的。

(更多)此处提供更多信息:http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx


编辑:

考虑一下,这里不需要通用差异。 List<T>实现了非通用IEnumerable。这就是foreach循环运行所需的全部内容,您只需将元素作为object类型,因此只需将其转换为IEnumerable而不是List<object>,所有内容都应该工作得很好。

答案 1 :(得分:4)

泛型和反射不能很好地混合,特别是对于列表。我强烈建议使用(非通用)IList,或者如果失败(某些通用列表没有实现),IEnumerable(从IEnumerable<T> : IEnumerable开始)并手动调用Add

我感到很痛苦,真的(我维护了一个OSS序列化API)。

答案 2 :(得分:1)

在C#3中,即使转换为类似Lists<T>的内容,也无法将Lists<T>投射到其他类型的List<Object>。即使在转换为List时也明确禁止它。

在4.0中,方差随着添加in and out关键字的界面而略有变化。

这是Eric Lippert的链接,解释了这种情况的原因和原因。

http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx

答案 3 :(得分:0)

你难道不能将它们转换为具有OfType()的对象吗?

List<object> listObjects = anObject.OfType<object>().ToList();

<强>更新

如果要求不是List<object>,那么这也可以,并且不会重复列表项:

var enumerableObjects = anObject.OfType<object>();