【问题标题】:Interface API calls with generic type使用泛型类型的接口 API 调用
【发布时间】:2019-12-06 11:31:21
【问题描述】:

我希望能够在 API 提供者之间切换并获得相同的结果。

我有一个名为 IApi 的接口,用于两个 API。

public interface IApi
{
    T GetData<T>();
}

然后我的两个 API 类实现了这个接口

public class ApiOne: IApi
{
    private IWebClient _client;
    public ApiOne(IWebClient client)
    {
        _client = client;
    }

    public T GetData<T>()
    {
        return _client.Get<T>($"{some specific url for this api");
    }
}

public class ApiTwo: IApi
{
    private IWebClient _client;
    public ApiTwo(IWebClient client)
    {
        _client = client;
    }

    public T GetData<T>()
    {
        return _client.Get<T>($"{some specific url for this api");
    }
}

这两个调用显然会根据 API 返回不同的 JSON 响应。我正在使用 Newtonsoft 将响应反序列化为强类型类。 这意味着我有 3 个数据模型。 1 代表每个 API 响应,第 3 位是我想将 API 响应转换成的,以便我只能使用一个数据模型作为通用类型。

public class ApiOneResponse
{
    public string FieldOne { get; set; }
    public string FieldTwo { get; set; }
}
public class ApiTwoResponse
{
    public string SomeOtherFieldOne { get; set; }
    public string SomeOtherFieldTwo { get; set; }
}

我怎样才能做到这一点,以便我的两个 API 调用都可以反序列化到同一个类,并且我可以用一个简单的单行来调用它?

public class CommonResponse
{
    public string CommonFieldOne { get; set; }
    public string CommonFieldTwo { get; set; }
}

我希望能够像下面这样简单地调用它

 static void Main(string[] args)
 {
    //some additional logic

    //call the API
    var response = _api.GetData<CommonResponse>();
 }

编辑 问题是 _webClient.Get 会尝试将 JSON 属性反序列化为 CommonResonse,并且每个 JSON 响应无法直接映射到 CommonResponse,因为每个响应的 JSON 键会不同。

下面是WebClient代码

public class WebClient : IWebClient
{
    public T Get<T>(string endpoint)
    {
        using (var client = new HttpClient())
        {
            HttpResponseMessage response = client.GetAsync(endpoint).Result;
            response.EnsureSuccessStatusCode();
            string result = response.Content.ReadAsStringAsync().Result;
            return JsonConvert.DeserializeObject<T>(result);
        }
    }
}

【问题讨论】:

  • 那么对_client.Get&lt;T&gt;() 的调用究竟是做什么的呢?您当前的设计允许var response = _api.GetData&lt;CommonResponse&gt;();,那么实际问题是什么?
  • @SashaStojanovic 你可以使用你的接口IApi generic 本身
  • @OndrejTucny 我已经编辑了原始问题,对最终问题进行了更好的解释。
  • WebClient 是 .NET Framework 中仍然可用的过时类的名称。使用该名称真的是个坏主意。使用.Result 并阻塞异步方法也是一个 的想法。网络操作是异步的,HttpClient 是异步的,所以你的代码也必须是异步的
  • PS:你也在滥用 HttpClient。这是一个线程安全的类,可以重用。检查You're using HttpClient wrong and it is destabilizing your softwareUse HttpClientFactory to implement resilient HTTP requests

标签: c# .net interface json.net implementation


【解决方案1】:

如果您总是返回 CommonResponse,则GetData 不需要是通用的:

public interface IApi
{
    CommonResponse GetData();
}

然后在每个实现中,将响应投射到您的CommonResponse

public class ApiOne: IApi
{
    private IWebClient _client;
    public ApiOne(IWebClient client)
    {
        _client = client;
    }

    public CommonResponse GetData()
    {
        var response = _client.Get<ApiOneResponse>($"{some specific url for this api");
        return new CommonResponse
        {
            CommonFieldOne = response.FieldOne,
            CommonFieldTwo = response.FieldTwo
        }
    }
}

【讨论】:

  • 多么真实!!! (掌心)。显示另一组眼睛可以做什么:D。谢谢大佬!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多