Cannot write off lists using Reflection in C #

I have a lot of problems with Reflection in C # at the moment. The application that I am writing allows the user to change the attributes of certain objects using a configuration file. I want to save an object model (user project) in XML. The function below is called in the middle of the foreach loop, iterating over the list of objects that contain all the other objects in the project inside them. The idea is that it recursively works to translate the object model into XML.

Don’t worry about calling “Unreal,” which slightly changes the name of objects 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 the attributes of the object are just strings, then they should write them as string attributes in XML. If the attributes of the objects are lists, then it must recursively call "ReflectToXML", passing itself as a parameter, thereby creating the nested structure that I need, which reflects the model of the object in memory well.

I have a problem with the line

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

The cast does not work, and it just returns null. During debugging, I changed the line to

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

hit a breakpoint on it to find out what GetValue returns. It returns a "General list of objects." Of course, should I be able to do this? It is annoying that temp becomes a general list of objects, but since I declared temp as a special object, I cannot skip it because it does not have an Enumerator.

How can I cycle through a list of objects when I only have the property property property of the class?

I know that at this moment I will keep a list of empty lines, but everything is in order. I would be glad to see that the structure is being maintained at the moment.

Thanks in advance

+4
source share
4 answers

Generics and reflections do not mix well, especially for listings. I would suggest using an (not generic) IList , or if that fails (some generic lists don't implement it), IEnumerable (starting with IEnumerable<T> : IEnumerable ) and calling Add manually.

I feel your pain, really (I support the OSS serialization API).

+4
source

I assume the actual value is not a List<object> , but rather like a List<string> or List<int> or some other type that is not exactly an object ?

If so, then the reason the throw occurs is because the general classes are neither covariant nor contravariant.

In C # 4.0, however, you can make a foreach loop foreach by casting to IEnumerable<object> , because interfaces can be co / contravariant.

(Many) more information here: http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx


Edit:

Thinking about this, here you do not need a general difference. List<T> implements a non-generic IEnumerable . That's all you need for the foreach to work, and you only need elements of type object , so just use its IEnumerable instead of List<object> , and everything should work fine.

+5
source

In C # 3, you cannot distinguish Lists<T> from other types of Lists<T> even when you click on List<Object> . It is clearly not allowed even when scrolling through a List.

In 4.0, variance changes slightly with interfaces adding in and out of keywords.

Here is a link to Eric Lippert explaining how and why this happens.

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

+1
source

Could you just pass them to objects using OfType ()?

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

Update:

If there was no requirement for List<object> , this will also work and will not duplicate list items:

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

Source: https://habr.com/ru/post/1306492/


All Articles