2013-04-02 49 views
3

我有一個方法可以簡化使用HttpClient調用。它使用方法HttpReponse.Content.ReadAsAsync()。結果從API獲取響應。正在投射簡單通用對象

這一切工作正常。我的方法看起來是這樣的:

public static T ExecuteAPIGetRequest<T>(string url, Dictionary<string, string> parameters) 
    { 

     HttpClient client = new HttpClient(); 
     //basic authentication 

     var t = new object(); 
     string baseURL = "myurl"; 

     //Execute request 
     HttpResponseMessage response = client.GetAsync(baseURL).Result; 

     if (response.IsSuccessStatusCode) 
     { 
      return response.Content.ReadAsAsync<T>().Result; 
     } 
     else 
     { 
      return (T)t; 
     } 
    } 

我的問題是,如果查詢失敗,它需要返回一個空類型T的這是好的,如果它是一個自定義類,我已經寫了,但它並不適用於工作對象如字符串或字符串[]。有任何想法嗎?

乾杯

大斑病

回答

7

嘗試返回default(T)

if (response.IsSuccessStatusCode) 
{ 
    return response.Content.ReadAsAsync<T>().Result; 
} 
else 
{ 
    return default(T); 
} 

default將返回null對於引用類型,和零點數值intdouble等..和相應的默認值自定義structenum

丹尼爾親切注意到一個問題:如果引用類型要返回默認的對象,而不是,你應該定義泛型約束new T()。現在,您可以使用對無參數構造函數的調用實例化類型爲T的對象。全部方法如下:

public static T ExecuteAPIGetRequest<T>(string url, 
             Dictionary<string, string> parameters) 
                    where T : new() 
{ 

    HttpClient client = new HttpClient(); 

    //basic authentication 

    string baseURL = "myurl"; 

    HttpResponseMessage response = client.GetAsync(baseURL).Result; 

    if (response.IsSuccessStatusCode) 
    { 
     return response.Content.ReadAsAsync<T>().Result; 
    } 
    else 
    { 
     return new T(); //returns an instance, not null 
    } 
} 

現在您將返回引用類型的默認對象,而不是null。開放式T只能採取類型,默認情況下(不帶參數)

+1

請注意:如果'T'是一個引用類型,它最可能是'null'。如果你想返回一個默認的*實例*,你需要爲'T'添加一個'new'約束並''返回新的T();'。 –

+0

謝謝伊利亞伊凡諾夫,那工作得很好!剛剛好。 – ncbl

+0

@DanielHilgarth可能我錯過了一些東西,但是'default(T)'爲原語和自定義結構返回正確的值。我剛測試過'double'和自定義結構。你不需要指定通用的約束,struct將始終有無參數的構造函數 –

0

我可以做你認爲這樣的做法的建議有構造....

class Program 
{ 
    static void Main(string[] args) 
    { 

     var client = new HttpClient(); 

     //basic authentication 

     string baseURL = "myurl"; 

     var link = Link<Foo>.Create(baseURL); 

     var response = client.SendAsync(link.CreateRequest()).Result; 

     var myfoo = link.ProcessResponse(response); 

    } 

} 


public class Link<T> 
{ 
    public Uri Target { get; set; } 

    public static Link<T> Create(string url) 
    { 
     return new Link<T>() {Target = new Uri(url)}; 
    } 

    public HttpRequestMessage CreateRequest() 
    { 
     return new HttpRequestMessage() {RequestUri = Target}; 
    } 

    public T ProcessResponse(HttpResponseMessage response) 
    { 
     if (response.IsSuccessStatusCode) 
     { 
      return response.Content.ReadAsAsync<T>().Result; 
     } 
     else 
     { 
      return new T(); //returns an instance, not null 
     } 
    } 
} 

public class Foo 
{ 

} 

通過封裝產生的機制鏈接到一個靜態工廠方法並將響應處理到ProcessResponse方法中,您可以獲得類似的重用性級別,但是您也可以重複使用相同的HttpClient。這使您可以充分利用DefaultRequestHeaders,並且它會阻止HttpClient在處置時關閉連接。另外,通過避免在同步方法內包裝Async調用,您可以讓調用代碼決定是阻止結果還是異步處理結果。您可能會在某些時候遇到死鎖問題,並與您當前的使用方式有關。結果。

創建鏈接類以封裝與解除引用URL相關的特定行爲的這種技術可能非常有用。添加可用於填充URI模板的參數很容易。你也可以用它來處理請求體。