我有这个senario,我需要为json反序列化提供一个类型,如何让它动态化?
此处代码使用示例类名(rd.ds.SDK.re.sa),但在实际代码中,将使用数据库中的数据构造类型。
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;
}
}
}
答案 0 :(得分:2)
使用JsonConvert.DeserializeObject
的{{3}}代替:
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;
}
}
}
显然,您需要将结果视为object
。由于在编译期间您不会知道对象的类型,因此使用泛型或使用反射来调用泛型重载是没有意义的。
您还应该创建这些类型的非通用版本:Result<T>
和AnalysisResult<T>
。
必须在运行时动态创建Result<AnalysisResult<dynamicalyCreatedAtRuntime>>
等类型才能完成反射,但这样做会有0个好处。这让人反感重新设计。
答案 1 :(得分:1)
MethodInfo.MakeGenericMethod
就是为了这个目的。
答案 2 :(得分:0)
如果可以,我会使用Netwonsoft.JSON(Json.Net)。
var json = ...get request body...
var type = Type.GetType("a.b.c");
var obj = JsonConvert.DeserializeObject(json, type);
与Json.NET合作也有很多帮助。如果您无法控制类,则可能无法使用,并且需要自定义转换。
如果您绝对必须调用Generic方法,则需要使用反射来手动构建调用。这很棘手,可能不值得。
var m = webRequest.GetType().GetMethod("ReadJsonResponseAs");
var func = m.MakeGenericMethod(type);
func.Invoke(webRequest, null); /* invoke func on webRequest object, no params */
你的泛型类型是否深层嵌套?如果是这样,你可能需要单独制作每个级别。
答案 3 :(得分:0)
使用反射来获取方法,然后通过使用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);