Reputation: 133
I'm facing a problem with reflection in c# and I can't find the answer.
I have a class that inherits from a generic type, and I'm trying to retrieve the type of T from this class, but it turns out that I can't!
Here is a example:
class Products : List<Product>
{}
The problem is that at runtime I don't know the type of T. So I tried to get the type like this:
Type itemsType = destObject.GetType().GetGenericArguments()[0]
It didn't work out.
Here is my method:
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;
}
The idea is to read an xml file and transform it in an object:
<?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>
in this case the node PRODUCTS would be my collection that inherits from List
any ideas on how to do this?
tks guys
Upvotes: 4
Views: 2487
Reputation: 86718
If you're just trying to figure out what the type of an IList
is, you should use something like this:
Type itemsType = destType.GetInterface(typeof(IList<>).Name).GetGenericArguments()[0];
Here's how you would use it in code:
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);
}
}
Upvotes: 1
Reputation: 887423
The Products
class isn't generic, so GetGenericArguments
doesn't return anything.
You need to get the generic arguments of the base type, like this:
Type itemType = destObject.GetType().BaseType.GetGenericArguments()[0];
However, this is not resilient; if an intermediary non-generic base type is introduced, it will fail.
Instead, you should find the type parameter of the IList<T>
implementation.
For example:
Type listImplementation = destObject.GetType().GetInterface(typeof(IList<>).Name);
if (listImplementation != null) {
Type itemType = listImplementation.GetGenericArguments()[0];
...
}
Upvotes: 6