Huzefa
Huzefa

Reputation:

Pass Type dynamically to <T>

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 Types 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

Answers (5)

Eamon Nerbonne
Eamon Nerbonne

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

Matthew Scharley
Matthew Scharley

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

Achim
Achim

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

Ulrik Rasmussen
Ulrik Rasmussen

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

Marc Gravell
Marc Gravell

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

Related Questions