Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic type from string value

I got a custom class, who relies on a generic type T to be passed along. I only know what type it is in string form, because that's how it's being sent. I've been searching around but can't seem to find exactly what I need. I can parse the string value to a type, but I need to parse it to... something, that I can pass as a generic parameter.


I've rewritten my problem, as such:

// Classes structure
namespace Mynamespace
{
    public interface IRequest
    {
    }

    public interface IHandler<T> where T : IRequest
    {
        void Handle(T item);
    }

    public class MyRequest : IRequest
    {
    }

    public class MyHandler : IHandler<MyRequest>
    {
        void Handle(MyRequest item)
        {
        }
    }
}

// The info I get, and I know typeString is a IRequest
string typeString = "My";
object requestItem = [insert xml parsing here];

// I then create a handler, to handle the request
Type typeHandler = Type.GetType("Mynamespace." + typeString + "Handler");
var handler = Activator.CreateInstance(typeHandler);

Type typeRequest = Type.GetType("Mynamespace." + typeString + "Request");

// what I want to do:
handler.Handle(requestItem);

I can't do that because handler and requestItem are just objects So I need to parse 'handler' to 'typeHandler', and requestItem to 'typeRequest'

Edit: I figured it out, I used InvokeMember to access it. :)

typeHandler.InvokeMember("Handle", BindingFlags.InvokeMethod, null, handler, new[] { requestItem });
like image 337
Rik De Peuter Avatar asked Sep 16 '11 22:09

Rik De Peuter


2 Answers

You need Type.MakeGenericType:

Type typeArgument = Type.GetType(string.Format("Mynamespace.{0}", typeString));
Type template = typeof(MyClass<>);

Type genericType = template.MakeGenericType(typeArgument);

object instance = Activator.CreateInstance(genericType);

Note that you can't cast this to a particular MyClass<T> because you don't know T - but it will be an instance of the right class at execution time.

like image 127
Jon Skeet Avatar answered Nov 04 '22 04:11

Jon Skeet


Type closedType = typeof(MyClass<>).MakeGenericType(myGeneric);
object obj = Activator.CreateInstance(closedType);

Note that unless you have a non-generic interface or base-type, it is very tricky to talk to this type of object (unless you cheat by using dynamic). For example, a non-generic interface can be helpful:

var obj = (ISomeInterface)Activator.CreateInstance(closedType);
obj.SomeMethodOnTheNonGenericInterface();
like image 40
Marc Gravell Avatar answered Nov 04 '22 06:11

Marc Gravell