0

My use case is this: There are a number of implementations of an interface, ICommand, that are JSON-serialized and sent to another system where they are deserialized and used. Part of the interface spec is a string property with the name of the specific type, since a type is needed for deserialization. Reading the type name from the JSON string and switching based on that is simple and it works, but it's also ugly and the switch needs to be updated every time a new implementation is added or a type name is changed for any reason:

Match match = Regex.Match(json, "\"TypeName\":\".*?\"");
if (match.Success)
{
    // Add cases here as new command types are defined
    switch (match.Value)
    {
        case "\"TypeName\":\"TypeNumberOne\"":
            return JsonConvert.DeserializeObject<TypeNumberOne>(json);

        default:
            break;
    }
}

What I'm hoping to be able to do is generalize the deserialization in some way. What I'm trying right now is reading the type name out of the JSON and using Type.GetType to get the type, which I'd like in some way to pass to JsonConvert.DeserializeObject<T>. I can get the type just fine, but I can't figure out how to pass it as the T. This

return JsonConvert.DeserializeObject<Type.GetType(string.Format("namespace.{0}", typeName))> (json);

and this

return JsonConvert.DeserializeObject<Type.GetType(string.Format("namespace.{0}", typeName)).MakeGenericType()> (json);

won't even compile; Intellisense says Operator '<' cannot be applied to operands of type 'method group' and 'Type' - evidently it's not seeing the Type-valued expression as a usable T.

Assigning the result of the expression to a variable:

Type commandType = Type.GetType(string.Format("VITL.Library.Commands.{0}", typeName));
return JsonConvert.DeserializeObject<commandType> (json);

results in 'commandType' is a variable but is used like a type.

Is there a way to derive a type at runtime such that it can be used in invoking a generic function?

Don R
  • 573
  • 4
  • 10
  • 2
    You're falling into the trap of confusing runtime typing with compile time typing. Perhaps something like https://stackoverflow.com/questions/1606966/generic-method-executed-with-a-runtime-type will be useful – Caius Jard Jun 23 '21 at 22:03
  • So, what you are trying to do is read a JSON file, extract the typename from somewhere in the file, and then deserialize the entire JSON file into an instance of that type. I'm assuming that the JSON schema for your various types is different. Since you don't post any example JSON or matching type code, I'm not going to give an answer (I don't like typing that much). But, if you have the typename, you can call `JsonConvert.DeserializeObject` via Reflection with `MakeGenericMethods`. It's a bit tricky since `JsonConvert` has about 7 different `DeserializeObject` implementations – Flydog57 Jun 23 '21 at 22:45
  • Post the source of at least two different types and the matching JSON, and you might get an answer. Otherwise, it's a lot of typing, and an answerer may not get the nuances in you particular case – Flydog57 Jun 23 '21 at 22:47
  • @CaiusJard 's link pointed me to an example that was very helpful, and his comment completely clarified the error in my thinking for me. I had failed to find the existing questions that bear on this because of differences in phrasing; I'd rather not delete this question in case someone finds it by searching language similar to mine, so it will be here to point them to the existing answers. – Don R Jun 24 '21 at 18:18
  • 1
    @Flydog57 How I ended up finding the right overload was calling **GetMethods** on **JsonConvert** and then iterating the array looking for the right name, the right number of parameters, and **IsGenericMethod** being true. Eh, it works – Don R Jun 25 '21 at 14:52

0 Answers0