对继承的泛型类型的反思

时间:2010-12-13 03:45:49

标签: c# generics reflection

我在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

的集合

关于如何做到这一点的任何想法?

tks guys

2 个答案:

答案 0 :(得分:6)

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 :(得分:1)

如果您只想弄清楚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); 
    } 
}