投射简单的通用对象

时间:2013-04-02 14:13:38

标签: c# asp.net-web-api dotnet-httpclient

我创建了一个方法来简化使用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。如果它是我编写的自定义类,这很好,但它不适用于像string或string []这样的对象。有什么想法吗?

干杯

大斑病

2 个答案:

答案 0 :(得分:7)

尝试返回default(T)

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

default会返回null作为参考类型,并将数字值intdouble等归零。以及自定义struct的相应默认值和enum

Daniel注意到一个问题:如果您想要返回默认对象而不是 null 的参考类型,则应该定义通用约束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 :(得分: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调用,您可以让调用代码决定是阻止结果还是异步处理它。您可能会在某些时候以您当前使用的方式遇到死锁问题。结果。

这种创建Link类以封装与取消引用URL相关的特定行为的技术非常有用。可以轻松添加可用于填充URI模板的参数。您也可以使用它来处理请求主体。