Отражение над унаследованными родовыми типами - PullRequest
4 голосов
/ 13 декабря 2010

У меня проблема с отражением в c #, и я не могу найти ответ.

У меня есть класс, который наследует от универсального типа, и я пытаюсь извлечь тип T из этого класса, но оказывается, что не могу!

Вот пример:

class Products : List<Product>
{}

Проблема в том, что во время выполнения я не знаю тип T. Поэтому я попытался получить такой тип:

Type itemsType = destObject.GetType().GetGenericArguments()[0]

Это не сработало.

Вот мой метод:

public static object Deserialize(Type destType, XmlNode xmlNode)
    {         
        object destObject = Activator.CreateInstance(destType);

        foreach (PropertyInfo property in destType.GetProperties())
            foreach (object att in property.GetCustomAttributes(false))
                if (att is XmlAttributeAttribute)
                    property.SetValue(destObject, xmlNode.Attributes[property.Name].Value, null);
                else if (att is XmlNodeAttribute)
                {
                    object retObject = Deserialize(property.PropertyType, xmlNode.Nodes[property.Name]);
                    property.SetValue(destObject, retObject, null);
                }

        if (destObject is IList)
        {
            Type itemsType = destObject.GetType().GetGenericArguments()[0];
            foreach (XmlNode xmlChildNode in xmlNode.Nodes)
            {
                object retObject = Deserialize(itemsType, xmlNode);
                ((IList)destObject).Add(retObject);
            }
        }

        return destObject;
    }        

Идея состоит в том, чтобы прочитать XML-файл и преобразовать его в объект:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<SETTINGS>
  <PRODUCTS>
    <PRODUCT NAME="ANY" VERSION="ANY" ISCURRENT="TRUE" />
    <PRODUCT NAME="TEST1" VERSION="ANY" ISCURRENT="FALSE" />
    <PRODUCT NAME="TEST2" VERSION="ANY" ISCURRENT="FALSE" />
  </PRODUCTS>
  <DISTRIBUTIONS>
    <DISTRIBUTION NAME="5.32.22" />
  </DISTRIBUTIONS>
</SETTINGS>

в этом случае узел PRODUCTS будет моей коллекцией, которая наследуется от List

есть идеи как это сделать?

ТКС, ребята

Ответы [ 2 ]

6 голосов
/ 13 декабря 2010

Класс Products не является универсальным, поэтому GetGenericArguments ничего не возвращает.

Вам необходимо получить универсальные аргументы базового типа, например:

Type itemType = destObject.GetType().BaseType.GetGenericArguments()[0];

Однако это не является устойчивым;если введен промежуточный неуниверсальный базовый тип, он потерпит неудачу.
Вместо этого вы должны найти параметр типа реализации IList<T>.

Например:

Type listImplementation = destObject.GetType().GetInterface(typeof(IList<>).Name);
if (listImplementation != null) {
    Type itemType = listImplementation.GetGenericArguments()[0];
    ...
}
1 голос
/ 13 декабря 2010

Если вы просто пытаетесь выяснить, какой тип IList, вы должны использовать что-то вроде этого:

Type itemsType = destType.GetInterface(typeof(IList<>).Name).GetGenericArguments()[0];

Вот как вы могли бы использовать егов коде:

var interface = destType.GetInterface(typeof(IList<>).Name);
var destList = destObject as IList;
// make sure that the destination is both IList and IList<T>
if (interface != null && destList != null)
{
    Type itemsType = interface.GetGenericArguments()[0];
    foreach (XmlNode xmlChildNode in xmlNode.Nodes) 
    { 
        object retObject = Deserialize(itemsType, xmlNode); 
        destList.Add(retObject); 
    } 
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...