使用通用类型的接口 API 调用
Interface API calls with generic type
我希望能够在 API 个提供商之间切换并获得相同的结果。
我有一个名为 IApi 的接口,用于两个 APIs。
public interface IApi
{
T GetData<T>();
}
然后我让我的两个 API classes 实现这个接口
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");
}
}
这两个调用显然 return 不同 JSON 响应取决于 API。我正在使用 Newtonsoft 将响应反序列化为强类型 classes。
这意味着我有 3 个数据模型。每个 API 响应 1 个,第 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 调用都可以反序列化为相同的 class 并且我可以用一个简单的衬里调用它?
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);
}
}
}
GetData
如果您总是返回 CommonResponse
:
则不需要通用
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
}
}
}
我希望能够在 API 个提供商之间切换并获得相同的结果。
我有一个名为 IApi 的接口,用于两个 APIs。
public interface IApi
{
T GetData<T>();
}
然后我让我的两个 API classes 实现这个接口
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");
}
}
这两个调用显然 return 不同 JSON 响应取决于 API。我正在使用 Newtonsoft 将响应反序列化为强类型 classes。 这意味着我有 3 个数据模型。每个 API 响应 1 个,第 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 调用都可以反序列化为相同的 class 并且我可以用一个简单的衬里调用它?
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);
}
}
}
GetData
如果您总是返回 CommonResponse
:
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
}
}
}