前言
上一篇《.net core实践系列之短信服务-Sikiro.SMS.Api服务的实现》讲解了API的设计与实现,本篇主要讲解编写接口的SDK编写还有API的测试。
或许有些人会认为,SDK的编写可以不需要,既然已经用了RESTful web服务与Swagger提供的接口描述,只要选择合适的接口调用框架,找到对应Swagger文档按需调用即可。
这个我赞同,特别在微服务架构下使用了API网关与服务发现。因此本篇也是借用编写SDK来模拟在客户端使用接口框架调用,并增加负载测试的讲解,供需要的朋友们分享。
项目源码地址:https://github.com/SkyChenSky/Sikiro.SMS.git
SDK
Software Development Kit的缩写,翻译中文为软件开发工具包,百度定义为软件工程师用于为特定的软件包、软件框架、硬件平台、操作系统等创建应用软件的开发工具的集合。而我们这里的SDK主要是以工具库的形式提供给部门内部使用API。
设计要点
- 尽量少的依赖
- 多形式方法重载
- 高可读性
从上三点得出,高可读的方法注释,方便使用的多重载(单条、多条、异步、同步),如涉及到枚举,不要依赖原有项目的其他库,应拷贝过来完整提供。
组件选择
- RestSharp
- .Net Standard
RestSharp
为了良好的调用RESTful API,我选择RestSharp这个RESTful接口调用框架。
源码地址:https://github.com/restsharp/RestSharp
优点
请求调用与响应结果的直观化:
步骤:
- 传入资源
- 定义动作
- 设置表述类型
- 传入实体参数
注意点
1.默认序列化类型为XML,应手动设置为JSON
RequestFormat = DataFormat.Json
2.反序列化有缺陷,对于实体内的类类型属性(List<T>、自定义类等),应再构造函数初始化赋默认值
public class SearchResponse { public SearchResponse() { Mobiles = new List<string>(); } public string Content { get; set; } public int Type { get; set; } public int Status { get; set; } public List<string> Mobiles { get; set; } [SerializeAs(Name = "_id", Attribute = true)] public string Id { get; set; } }
示例
public static class Sms { private static RestClient _client; private static string Host { get; set; } public static void Init(string host) { Host = host; _client = new RestClient(Host); } public static async Task<Response> SendAsync(List<SendEntity> sendList) { var request = new RestRequest("sms", Method.POST) { RequestFormat = DataFormat.Json }; request.AddBody(sendList); var response = await _client.ExecuteTaskAsync(request); return ToResponse(response); } public static async Task<Response> SendAsync(SendEntity sendEntity) { return await SendAsync(new List<SendEntity> { sendEntity }); } public static Response Send(List<SendEntity> sendList) { var request = new RestRequest("sms", Method.POST) { RequestFormat = DataFormat.Json }; request.AddBody(sendList); var response = _client.Execute(request); return ToResponse(response); } public static Response Send(SendEntity sendEntity) { return Send(new List<SendEntity> { sendEntity }); } public static Response<SearchResponse> Get(string id) { var request = new RestRequest("sms/{id}", Method.GET); request.AddUrlSegment("id", id); var response = _client.Execute<SearchResponse>(request); return ToResponse(response); } public static Response<List<SearchResponse>> Search(SearchEntity searchModel) { var request = new RestRequest("sms/_search", Method.POST) { RequestFormat = DataFormat.Json }; request.AddBody(searchModel); var response = _client.Execute<List<SearchResponse>>(request); return ToResponse(response); } private static Response<T> ToResponse<T>(IRestResponse<T> t) { var msg = t.IsSuccessful ? t.StatusCode.ToString() : t.Content; return new Response<T> { Body = t.Data, StateCode = t.StatusCode, Message = t.ErrorMessage ?? msg, IsSuccess = t.IsSuccessful }; } private static Response ToResponse(IRestResponse t) { var msg = t.IsSuccessful ? t.StatusCode.ToString() : t.Content; return new Response { StateCode = t.StatusCode, Message = t.ErrorMessage ?? msg, IsSuccess = t.IsSuccessful }; } }
.Net Standard
公司里除了有新用的.NET Core项目还有大量的存量.NET Framework旧项目。
.NET Standard是一种规范,无法以此建立应用,但他能以库的形式作为支撑。.NET Standard的出现为了解决以编写一次的库来同时支持多个平台(.NET Framework、.NET Core、Xamarin)的使用。
为了实现多平台的API标准映射,不同版本的映射与数量也随着不一样
.NET Standard |
1.0 | 1.1 | 1.2 | 1.3 | 1.4 | 1.5 | 1.6 | 2.0 |
.NET Core | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 1.0 | 2.0 |
.NET Framework | 4.5 | 4.5 | 4.5.1 | 4.6 | 4.6.1 | 4.6.1 | 4.6.1 | 4.6.1 |
Mono | 4.6 | 4.6 | 4.6 | 4.6 | 4.6 | 4.6 | 4.6 | vNext |
Xamarin.iOS | 10.0 | 10.0 | 10.0 | 10.0 | 10.0 | 10.0 | 10.0 | vNext |
Xamarin.Android | 7.0 | 7.0 | 7.0 | 7.0 | 7.0 | 7.0 | 7.0 | vNext |
Universal Windows Platform | 10.0 | 10.0 | 10.0 | 10.0 | 10.0 | vNext | vNext | vNext |
Windows | 8.0 | 8.0 | 8.1 | |||||
Windows Phone | 8.1 | 8.1 | 8.1 | |||||
Windows Phone Silverlight | 8.0 |
.Net Standard编译多版本程序集设置
右键编辑项目.csproj,可见下图原本应该是TargetFramework的节点,改为TargetFrameworks(多了个s),通过分号区分不同的程序集,因为RestSharp需要到.NET Framework4.6支持,因为我填入了net46。