I am having a lot of trouble with Reflection in C# at the moment. The app I am writing allows the user to modify the attributes of certain objects using a config file. I want to be able to save the object model (users project) to XML. The function below is called in the middle of a foreach loop, looping through a list of objects that contain all the other objects in the project within them. The idea is, that it works recursively to translate the object model into XML.
Dont worry about the call to "Unreal" that just modifes the name of the objects slightly if they contain certain words.
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, "");
}
}
If an object attributes are just strings then it should be writing them out as string attributes in the XML. If an objects attributes are lists, then it should recursively call "ReflectToXML" passing itself in as a parameter, thereby creating the nested structure I require that nicely reflect the object model in memory.
The problem I have is with the line
List<object> listObjects = (aInfo.GetValue(anObject,null) as List<object>);
The cast doesn't work and it just returns null. While debugging I changed the line to
object temp = aInfo.GetValue(anObject,null);
slapped a breakpoint on it to see what "GetValue" was returning. It returns a "Generic list of objects" Surely I should be able to cast that? The annoying thing is that temp becomes a generic list of objects but because i declared temp as a singular object, I can't loop through it because it has no Enumerator.
How can I loop through a list of objects when I only have it as a propertyInfo of a class?
I know at this point I will only be saving a list of empty strings out anyway, but thats fine. I would be happy to see the structure save out for now.
Thanks in advance
I'm assuming that the actual value is not a List<object>
but is something like a List<string>
or List<int>
or some other type that isn't exactly object
?
If so, then the reason that the cast is failing is because generic classes are neither co- nor contravariant.
In C# 4.0, however, you will be able to make the foreach
loop work by casting to IEnumerable<object>
because interfaces can be co/contravariant.
(Much) more information here: http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx
Edit:
Thinking about it, you don't need generic variance here. List<T>
implements the non-generic IEnumerable
. This is all you need for the foreach
loop to operate, and you only need the elements as type object
so just cast it to an IEnumerable
instead of List<object>
and everything should work fine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With