2014-02-28 163 views
1

我有這個塞納里奧我需要提供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

可能重複: //stackoverflow.com/questions/1151464/how-to-dynamically-create-generic-c-sharp-object-using-reflection) – Yuriy

+0

是'ReadJsonResponseAs'的擴展方法?是在第三方庫中定義的嗎?檢查API是否暴露了一個帶有'Type'對象而不是泛型類型參數的重載。 – dcastro

+3

不是重複的。這是調用一個通用的方法。 –

回答

2

使用JsonConvert.DeserializeObject代替this overload

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個好處。這尖叫重新設計。

+0

我不知道我知道我該如何使結果和AnalysisResult 非通用並利用它們來提供一個類型。 – user3357776

+0

@ user3357776是「結果」您創建的類型? – dcastro

+0

是的,所有這些都是我的類型 – user3357776

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中也有很多幫助。如果您不控制類,這可能不起作用,並且需要自定義轉換。

如果你絕對必須調用泛型方法,您將需要使用反射來手動構建呼叫。這變得棘手,可能不值得。

var m = webRequest.GetType().GetMethod("ReadJsonResponseAs"); 
var func = m.MakeGenericMethod(type); 
func.Invoke(webRequest, null); /* invoke func on webRequest object, no params */ 

您的泛型是深度嵌套的嗎?如果是這樣,你可能不得不分別製作每個關卡。

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); 
[如何使用反射動態創建通用的C#對象?(HTTP的