目前我在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时,如何遍历对象列表?
我知道在这一点上我只会保存一个空字符串列表,但那很好。我很高兴看到结构现在省去了。
提前致谢
答案 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>();