2013-04-02 68 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模板的参数很容易。你也可以用它来处理请求体。