1

I have a Json deserialiser class that is created using a generic parameter like this:

Deserializer<T> results = Deserializer<T>.FromFile(file);

Where T is the interface that an arbitrary number of types implement.

I'd like T to be chosen by the name of the class in the form of a string such as "Person" and the class Person implements T.

So it could be written like this:

Deserializer<Type.GetType("Person")> results = Deserializer<Type.GetType("Person")>.FromFile(file);

I have tried exactly this above and it gives me an error:

Using the generic type 'Deserializer<T>' requires 1 type arguments

I've also looked at this

http://social.msdn.microsoft.com/Forums/en-US/80690cd9-d1f2-4888-9c95-62305de9ced4/using-typegettype-with-generics

but trying to use some of these resulted in other errors such as:

randomVariable is a 'field' but is used like a 'type'

Is there a mistake in my code or am I going about this the wrong way?

How can I get this to work?

Solution My final code was

        Type genericType = typeof(Deserializer<>);
        Type[] typeArgs = {Type.GetType("Person")};
        Type deserialiserType = genericType.MakeGenericType(typeArgs);
        object repository = Activator.CreateInstance(deserialiserType);

        MethodInfo genericMethod = deserialiserType.GetMethod("FromFile");
        genericMethod.Invoke(repository, new[] {file});

Thank you all for your help

Sean Forman
  • 400
  • 4
  • 16
  • 1
    Can you elaborate a bit more on your goal, what you say doesn't entirely compute. Are you trying to build an `interface` or `class` based on the JSON or are you trying to assign the value to a class that exist? – Greg Apr 30 '14 at 22:46
  • Tell us what serializer you are using so we can give you some advice. – Simon Whitehead Apr 30 '14 at 22:47
  • What if the class name provided implements multiple interfaces? – dyson Apr 30 '14 at 22:48
  • I think this may be quite useful for you: http://stackoverflow.com/questions/11107536/convert-string-to-type-c-sharp. From Jon Skeet's own mouth! – adaam Apr 30 '14 at 22:49
  • @barrick I can guarantee it only implements once class ever. – Sean Forman Apr 30 '14 at 23:08
  • @Ellimist0 In that case, to get to the interface, you can call FindInterfaces() on the type returned from the advice above; this will return an Array of Type[], and so the item at index 0 will be the interface you need. – dyson Apr 30 '14 at 23:13

4 Answers4

2

This is the wrong approach because the generic field requires a type and not an object of the Type class.

However, there is already a solution. How do I create a generic class from a string in C#?

Community
  • 1
  • 1
Martin Braun
  • 10,906
  • 9
  • 64
  • 105
  • Thanks for the link, that gets me all the way to the line: `MethodInfo closedMethod = genericMethod.MakeGenericMethod(typeof(Something));` But I don't know what Something is, which brings me full circle to the original problem – Sean Forman Apr 30 '14 at 23:04
  • Thank you, I went one step too far when I could invoke the method using the genericMethod option – Sean Forman Apr 30 '14 at 23:21
2

Using the answer in ModiX's link applied to your code, should result in something like this:

Type genericType = typeof(Deserializer<>);
Type[] typeArgs = { Type.GetType("Person") };
Type deserializerType = genericType.MakeGenericType(typeArgs);

object deserializer = Activator.CreateInstance(deserializerType);

MethodInfo fromFileMethod = deserializerType.GetMethod("FromFile");
fromFileMethod.Invoke(deserializer, new[] { file });

The line

MethodInfo closedMethod = genericMethod.MakeGenericMethod(typeof(Something));

is used if your method is generic, in your case if it would look something like this:

Deserializer<T>.FromFile<T2>(...)
Shai Cohen
  • 6,074
  • 4
  • 31
  • 54
Håkan Fahlstedt
  • 2,040
  • 13
  • 17
0

Generic parameters must be "real type names", because they should be resolvable at build-time.

Type.GetType is a runtime method.

You've got many choices, for example :

This will give you the ability tu use runtime types.

  • See if deserializer can "automatically" deserialize to an instance of the good type (boxed in object) and just cast it to expected type.

  • Change your implementation to call Deserializer with the good generic parameter according the data to deserialize.

AFract
  • 8,868
  • 6
  • 48
  • 70
0

I believe what your attempting to do is implement this:

public interface Dynamic <T>
{
     T GetObject(string derserialize);
}

So essentially your class would inherit Dynamic, defining your generic type at that moment. Then you would essentially implicit or explicitly implement the method GetObject. It would accept your JSON data, then you could perform your desired logic to return it as the type of your choice.

Greg
  • 11,302
  • 2
  • 48
  • 79