Reputation:
I have this senario where I need to provide a type for json deserialization, how do I make it dynamic?
Here the code uses an example class name(rd.ds.SDK.re.sa), but in the real code the type will be constructed using data from database.
Type dynamicalyCreatedAtRuntime = Type.GetType("rd.ds.SDK.re.sa");
var response = webRequest.ReadJsonResponseAs<Result<AnalysisResult<dynamicalyCreatedAtRuntime>>();
public static T ReadJsonResponseAs<T>(this HttpWebRequest webRequest)
{
using (System.IO.Stream responseStream = webRequest.GetResponse().GetResponseStream())
{
using (System.IO.StreamReader sr = new System.IO.StreamReader(responseStream))
{
T result = JsonConvert.DeserializeObject<T>(sr.ReadToEnd());
responseStream.Close();
return result;
}
}
}
Upvotes: 1
Views: 105
Reputation: 68660
Use this overload of JsonConvert.DeserializeObject
instead:
public static object ReadJsonResponseAs(this HttpWebRequest webRequest, Type type)
{
using (System.IO.Stream responseStream = webRequest.GetResponse().GetResponseStream())
{
using (System.IO.StreamReader sr = new System.IO.StreamReader(responseStream))
{
object result = JsonConvert.DeserializeObject(sr.ReadToEnd(), type);
responseStream.Close();
return result;
}
}
}
Obviously, you'll need to treat the result as an object
. Since you won't know the type of the object during compile-time, there's no point in using generics or using reflection to invoke the generic overload.
You should also create a non generic version of these types: Result<T>
and AnalysisResult<T>
.
Having to dynamically create types such as Result<AnalysisResult<dynamicalyCreatedAtRuntime>>
at runtime could be done with reflection, but there would be 0 benefits in doing so. This screams for a redesign.
Upvotes: 2
Reputation: 103365
Use reflection to get the method to start with, then "construct" it by supplying type arguments with MakeGenericMethod:
Type dynamicalyCreatedAtRuntime = Type.GetType("rd.ds.SDK.re.sa");
MethodInfo method = webRequest.GetType().GetMethod("ReadJsonResponseAs");
MethodInfo generic = method.MakeGenericMethod(dynamicalyCreatedAtRuntime );
generic.Invoke(this, null);
Upvotes: 0
Reputation: 8674
If you can, I would use Netwonsoft.JSON (Json.Net) for this.
var json = ...get request body...
var type = Type.GetType("a.b.c");
var obj = JsonConvert.DeserializeObject(json, type);
Lots of help out there for working with Json.NET too. This may not work if you aren't in control of the classes, and they need custom conversions.
If you absolutely must call the Generic method, you are going to need to use reflection to manually construct the call. This gets tricky, and probably isn't worth it.
var m = webRequest.GetType().GetMethod("ReadJsonResponseAs");
var func = m.MakeGenericMethod(type);
func.Invoke(webRequest, null); /* invoke func on webRequest object, no params */
Are your generic types that deeply nested? If so you will probably have to make each level separately.
Upvotes: 0