Reputation:
See i have a situation like this...
object myRoledata = List<Roles>() --> (some list or Ienumerable type)
Now i have a generic method which creates an XML object from List<T>
-
Something like this..
public string GetXML<T>(object listdata)
{
List<T> objLists = (List<T>)Convert.ChangeType(listData, typeof(List<T>));
foreach(var obj in listdata)
{
//logic to create xml
}
}
Now in order to run this method I have to do like this:
string xml = GetXML<Roles>(myRoledata);
Now i dont know what Type
may come to me to be passed to GetXML
method. I have a method which will call GetXML
for different Type
s e.g. Roles
, Users
etc
now i can get the Type
within the List<>
like this
Type genericType = obj.GetType().GetGenericArguments()[0];
but cannot pass it like this
string xml = GetXML<genericType>(myRoledata);
Is there anyway in which i can pass any genericTypes
to GetXML
method?
Upvotes: 15
Views: 37518
Reputation: 48176
This is a problem you probably want to avoid solving. It is possible, via reflection, to call methods dynamically without statically resolving them - but it kind of defeats the whole point of the type-annotations.
Either do this:
public string GetXML(IEnumerable listdata) {
foreach(object obj in listdata)
//logic to create xml
}
... which you now can call with any IEnumerable
, or write it the "modern" way as:
public string GetXML(IEnumerable<object> listdata) {
foreach(object obj in listdata)
//logic to create xml
}
... which you can call with any IEnumerable
via GetXML(someEnumerable.Cast<object>())
and in C# 4.0 even directly by covariance.
If you need the type of an element runtime, you can get it using .GetType()
on each element, or you can just pass it in as a parameter (and provide an override for backwards-compatibility):
public string GetXML(Type elementType, IEnumerable<object> listdata) {
foreach(object obj in listdata)
//logic to create xml
}
public string GetXML<T>(IEnumerable<T> listdata) {
return GetXML(typeof(T),listdata.Cast<object>());
}
Incidentally, if you're constructing XML, a string is probably a less robust return-type choice: if possible, you could work with something like an XElement
instead - and get xml-validity guarantee's to boot.
Upvotes: 2
Reputation: 132524
I don't know your situation, but is it possible to rewrite your function as:
public string GetXML<T>(IEnumerable<T> listdata)
{
foreach(var obj in listdata)
{
//logic to create xml
}
}
Then it can be called as:
List<Role> myList;
GetXML(myList);
You can add type parameters as far back as needed to support it, till you get to somewhere that does know what the solid type is.
Upvotes: 2
Reputation: 15722
You have the right idea, but you are using the wrong method. Have a look at Type.MakeGenericType or MethodInfo.MakeGenericMethod. It will take a few more lines than your example, but it should be simple to solve.
GetGenericArguments() can be used to get the Roles type from a List. It's the differnt way around.
Btw: Looks like your implementing some kind of XML serialization. Make sure you check existing classes, before reinventing the wheel. ;-)
Upvotes: 0
Reputation: 1128
Since you cast your listdata parameter as a List< T> in the first line of your method, why don't you just change the method signature to
public string GetXML<T>(List<T> listdata)
That way, you don't have to use reflection to get the generic arguments.
EDIT: I see that you need to be able to accept IEnumerable collections, and not just lists. So, consider changing your method signature to
public string GetXML<T>(IEnumerable<T> listdata)
Upvotes: 7
Reputation: 1064244
To do that, you need to use reflection;
typeof(SomeClass).GetMethod("GetXML").MakeGenericMethod(genericType)
.Invoke(inst, new object[] {myRoleData});
where inst
is null
if it is a static method, this
for the current instance (in which case you can also use GetType()
instead of typeof(SomeClass)
), or the target object otherwise.
Upvotes: 8