Generic type from string value

13,309

Solution 1

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

typeHandler.InvokeMember("Handle", BindingFlags.InvokeMethod, null, handler, new[] { requestItem });

Solution 2

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.

Solution 3

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();
Share:
13,309
Rik De Peuter
Author by

Rik De Peuter

Updated on July 06, 2022

Comments

  • Rik De Peuter
    Rik De Peuter almost 2 years

    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 });
    
  • Daniel Pryden
    Daniel Pryden over 12 years
    +1. Also note that, although you can't cast the result to a particular MyClass<T>, you may want to define a non-generic interface (e.g. IMyClass) and cast to that.
  • Jon Skeet
    Jon Skeet over 12 years
    @Daniel: Indeed. I thought I'd hold back from that until the OP gave more information :)
  • Rik De Peuter
    Rik De Peuter over 12 years
    This is what I sort of do as well already, to create a new instance. But that returns an object, and that object, I need to parse to a MyClass<T>. Because the 'MyClass' has a void that requires the T.
  • Rik De Peuter
    Rik De Peuter over 12 years
    @Daniel: In my real code I use an interface, and an extra class in between, but I tried here to make a sample of what my problem is, without making it too complicated. :)
  • Daniel Pryden
    Daniel Pryden over 12 years
    @FrieK: What do you mean, "has a void that requires the T"? You aren't going to be able to use compile-time generic dispatch based on a type that is only determined at run time -- it's simply not possible. Perhaps dynamic will do what you want, but I don't understand your problem well enough to be sure.
  • Rik De Peuter
    Rik De Peuter over 12 years
    Hmm, I think it's the impossible one that I want, but I am rewriting my question to make it more obvious, I hope.
  • Rik De Peuter
    Rik De Peuter over 12 years
    Hi Daniel, I've rewritten my problem, maybe it will make more sense like that. :) Thanks again!