0

How can I pass a generic method type parameter as a variable to it? Below given is the crud example of what I want to achieve. It's just for a demo purpose, not the actual code. I can use if...else or switch to go through passed category and call generic method with corresponding type parameter.

[HttpGet]
[Route("{category}")]
public IActionResult Get(string category)
{
    object data = new object();
    string json = GetData(category);
    if (category == "User")
    {
        data = JsonConvert.DeserializeObject<User>(json);
    }
    else if (category == "Organization")
    {
        data = JsonConvert.DeserializeObject<Organization>(json);
    }

    return Ok(data);
}

Assume GetData is a function which gives me a collection in a JSON format based on passed category. I want to call a generic method, DeserializeObject<T>(...), which requires a type parameter. The class which refers the type parameter is related to passed category. How to achieve like given below?

[HttpGet]
[Route("{category}")]
public IActionResult Get(string category)
{
    string json = GetData(category);
    T categoryType = GetCategoryType(category); // what should be here???
    object data = JsonConvert.DeserializeObject<categoryType>(json);

    return Ok(data);
}
Farhan Ghumra
  • 15,180
  • 6
  • 50
  • 115
  • 4
    "How can I pass a generic method type parameter as a variable to it?" - that isn't how generics are _meant_ to be used. Generics enable _static_ (i.e. compile-time) type information to be reified - for this scenario you should stick to good ol' fashioned vtable polymorphism. – Dai Jul 14 '21 at 13:53
  • 2
    A good counter-example to your notion is `Get( category: DeleteEntireFileSystem )`. You should never let external/remote clients have full control over deserialization: it leads to far too many vulnerabilities. – Dai Jul 14 '21 at 13:54
  • 3
    Does this answer your question? [Setting generic type at runtime](https://stackoverflow.com/questions/2604743/setting-generic-type-at-runtime) – Franz Gleichmann Jul 14 '21 at 13:55
  • "which gives me a collection in a JSON format based on passed category" - I'll bet you $50 USD that **this is not what it does** - simply because if you call `GetData( "nextweekslotterynumbers" )` you _won't_ get a JSON array of 7 numbers 0-49. You need to find out **exactly what** data `GetData` can return and then enforce that restriction in your controller action. This is part of _defence in depth_. – Dai Jul 14 '21 at 13:56
  • 1
    @Dai please don't focus on what `GetData` function is doing. It was taken just as an example. – Farhan Ghumra Jul 14 '21 at 14:12
  • @FarhanGhumra I disagree, it's actually fundamental to the issue at-hand because whatever `GetData` does **directly** affects what your code is capable of. If you just used `GetData` as a hypothetical then that's not helping anyone, please post your **actual** problem. – Dai Jul 14 '21 at 15:05

1 Answers1

1

JsonConvert.DeserializeObject does not require generics, it also accepts a Type object. Generics is not the right solution here.

Instead use this overload

JsonConvert.DeserializeObject(json, Type.GetType(yourNamespace + category))

I strongly suggest you maintain a whitelist of possible types if you are receiving the type name from user input.

Charlieface
  • 52,284
  • 6
  • 19
  • 43
  • 1
    Here question is about any generic function not for Json.NET's `DeserializeObject` function. I mentioned it as an example just. – Farhan Ghumra Jul 14 '21 at 14:14
  • 1
    Then the duplicate is whta you want. If it was just an example of some generic code then you should have made that clear. I have answered the question that was asked – Charlieface Jul 14 '21 at 14:15