强制转换简单泛型对象

本文关键字:泛型 对象 简单 转换 | 更新日期: 2023-09-27 18:06:57

我创建了一个方法来简化使用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[]。什么好主意吗?

欢呼

NCBL

强制转换简单泛型对象

尝试返回default(T)

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

default将为引用类型返回null,并为零数值int, double等。以及相应的自定义structenum的默认值。

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只能接受默认具有构造函数(不带参数)的类型

我可以建议您考虑这样的方法....

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调用包装在同步方法中,您可以让调用代码决定是阻塞结果还是异步处理它。当前使用. result的方式可能会在某些时候遇到死锁问题。

这种创建Link类来封装与取消引用URL相关的特定行为的技术可能非常有用。添加可用于填充URI模板的参数是很容易的。你也可以用它来处理请求正文