0

I'm trying to call a generic method with a type detemirned at runtime. This call: Type type = ...; jToken.Value.Value<type>(); on a JToken object.

I've come this far, and I believe I'm almost there. But I'm getting a "parameter count mismatch" exception when calling Invoke. I can't figure out why.

public void Foo(JObject obj, Type type)
{
    foreach (var valuePair in obj)
    {
        JToken jToken = valuePair.Value;
        var genericMethod = jToken.GetType().GetMethod("Value").MakeGenericMethod(new Type[] {type});
        // should call jToken.Value<type>()
        var value = genericMethod.Invoke(jToken, null);
    }
}
Snæbjørn
  • 10,322
  • 14
  • 65
  • 124

2 Answers2

1

The Value() method of JObject require a Key Parameter, but you are not specifying that parameter, so can't find a method with 0 parameters and throw the exception.

frikinside
  • 1,244
  • 1
  • 9
  • 19
  • Okay here's a strange one. If I put a breakpoint after the `jToken` declaration and in the immediate window type: `jToken.Value()` then I get the expected result. If I however put `jToken.Value("someKey")` then it fails with "Cannot access child value on Newtonsoft.Json.Linq.JValue" – Snæbjørn Mar 13 '14 at 12:22
  • 1
    @Snæbjørn There's a reason for that. The JToken class has a method named "Value" with one parameter, the key. But, there are extension methods for the instances of JToken, one of them is Value(), that's the method you are calling in the inmediate window, not the Value method of the JToken class. That method not even exists in JToken, it not belongs there, it's a static method. For the compiler using this method is the same as write `StaticExtensionClass.Value(jToken)` – frikinside Mar 13 '14 at 15:15
  • @Snæbjørn A `JValue` doesn't have a child. It represents a primitive value such as a string, number, bool or null. You can check its type by looking at the `Type` property. – Brian Rogers Mar 13 '14 at 15:25
  • @frikinside I see, perhaps I should refactor into using the static method as it seems cleaner :) – Snæbjørn Mar 13 '14 at 16:43
  • Haha okay extension methods are not "cleaner" to call via reflection. http://stackoverflow.com/questions/1452261/how-do-i-invoke-an-extension-method-using-reflection – Snæbjørn Mar 13 '14 at 17:01
  • @Snæbjørn I'm glad to see that you figured out! The generic type always ofuscate the Invoke Member strategy, sometimes it cleanner (but not always better) to look for a workaround to avoid them. – frikinside Mar 13 '14 at 17:14
1

JToken.Value needs a parameter: the key of the value. So you would do:

var value = genericMethod.Invoke(jToken, new[] { valuePair.Key });
Jon
  • 428,835
  • 81
  • 738
  • 806
  • Thanks this helped a lot. However it needs to be `Invoke(obj, new[] { valuePair.Key });` else it'll throw "Cannot access child value on Newtonsoft.Json.Linq.JValue". There seems to be a method that takes 0 parameters if you call fx `jToken.Value()` it doesn't require a parameter, but the reflection engine doesn't seem to find it. So instead I need to call `obj.Value("keyname")` – Snæbjørn Mar 13 '14 at 12:46