时间飞快,转眼半年,碌碌无为,眼下就要三十而立,回想三年前的今天,我将NetworkSocket库开放到github,一直在更新与学习,不求有这个库能有多好,只求本身在过程能成长,将领悟到一些思想应用到库里面去。今天,我来给你们介绍半年前在github开放的WebApiClient这个库,正如NetworkSocket同样,它正在渐渐从眇小变得强大,从简单变得抽象、易用、可高度扩展,它将带你进入不一个和以往彻底不一样风格的调用http接口的世界。git
通常的,咱们须要new 一个HttpClient实例,而后准备请求url、请求body的HttpContent,而后发送,等待接收,解析回复内容.....github
这些都是须要一行一行代码来实现,代码里不只表现了“作什么(What)”,并且更多表现出“如何(How)”完成工做这样的实现细节,大概想一想代码像下面:web
/// <summary> /// 更新用户信息 /// 使用application/json提交 /// </summary> /// <param name="user"></param> /// <returns></returns> async static Task<UserInfo> UpdateAsync(UserInfo user) { var httpClient = new HttpClient(); var serializer = new JavaScriptSerializer(); var json = serializer.Serialize(user); var content = new StringContent(json, Encoding.UTF8, "application/json"); var url = "http://localhost:9999/webapi/user/updateWithJson"; var response = await httpClient.PostAsync(url, content); var resJson = await response.Content.ReadAsStringAsync(); var resUser = serializer.Deserialize<UserInfo>(resJson); return resUser; }
服务端任何接口的小变化,都直接影响到咱们接口调用的某行具体代码,若是有100个接口,这代码的维护也不小。sql
WebApiClient的设计能够解放使用者的劳动力,只须要使用者根据http接口来定义一份.Net的interface,在接口里描述你想要什么(what i wan),但不须要实现这份interface(how it do),大概以下:编程
[HttpHost("http://localhost:9999")] public interface UserApi { [HttpPost("/webapi/user/UpdateWithJson")] Task<UserInfo> UpdateWithJsonAsync([JsonContent] UserInfo user); }
那么,接口的实现者给谁来完成呢?给WebApiClient来完成,它很聪明,知道你想要什么,这个正像咱们写一条sql:select * from table同样,只有what,没有how。json
使用者编写的interface,能够与服务端接近彻底一致,在编写接口或文档对照方面至关容易。api
上面的[HttpPost]和[JsonContent],用来标记是干什么(不是怎么干)缓存
var userApi = new HttpApiClient().Implement<UserApi>(); var resUser = await userApi.UpdateWithJsonAsync(user);
使用Castle来动态实现interface的实例,并得到实例方法调用的拦截,在拦截层,一一调用与方法相关标记的Atribute,Attribute是真正的逻辑实现者,每一个Attribute只关注本身应该作什么。架构
ApiActionContext用于描述接口的详细信息以及接口周边的其它信息,在拦截interface的实例某方法以后,都生成一份ApiActionContext实例,但实例的不少属性是缓存中获取的,任何特性在执行的时候,均可以访问和修改这个ApiActionContext。app
一、IHttpActionAttribute (ApiActionContext) // 与Api方法相关
二、IApiParameterAttribute (ApiActionContext) // 与 api参数相关
三、IApiActionFilterAttribute (ApiActionContext) // 与Api请求先后有关
四、IApiReturnAttribute (ApiActionContext) // 与api返回值相关
这4个Attribute接口有着各自的职责,前三者一个共同的目标:构造和影响一个请求内容对象HttpRequestMessage,第4个的目标是:从回复的HttpResponseMessage中获得接口的返回值
在拦截器里,按照IApiActionAttribute > IApiParameterAttribute > IApiActionFilterAttribute > IApiReturnAttribute的顺序,将与方法的全部特性都执行,就能够完成接口的调用,大概实现以下:
/// <summary> /// 异步执行api /// </summary> /// <param name="context">上下文</param> /// <returns></returns> private async Task<object> ExecuteInternalAsync(ApiActionContext context) { var apiAction = context.ApiActionDescriptor; foreach (var actionAttribute in apiAction.Attributes) { await actionAttribute.BeforeRequestAsync(context); } foreach (var parameter in apiAction.Parameters) { foreach (var parameterAttribute in parameter.Attributes) { await parameterAttribute.BeforeRequestAsync(context, parameter); } } foreach (var filter in apiAction.Filters) { await filter.OnBeginRequestAsync(context); } // 执行Http请求,获取回复对象 var httpClient = context.HttpClientContext.HttpClient; context.ResponseMessage = await httpClient.SendAsync(context.RequestMessage); foreach (var filter in apiAction.Filters) { await filter.OnEndRequestAsync(context); } return await apiAction.Return.Attribute.GetTaskResult(context); }
绝对主机域名:[HttpHost]
请求方式与路径:[HttpGet]、[HttpPost]、[HttpDelete]、[HttpPut]、[HttpHead]和[HttpOptions]
代理:[Proxy]
请求头:[Header]
返回值:[AutoReturn]、[JsonReturn]、[XmlReturn]
使用者能够本身扩充更多特性。
路径或query:[PathQuery]、[Url]
请求头:[Header]
请求Body:[HttpContent]、[JsonContent]、[XmlContent]、[FormContent]、[MulitpartConten]
使用者能够本身扩充更多特性。
MulitpartFile类(表单文件)、Url类(请求地址)、Proxy类 (请求代理)
这些特殊参数类型在参数里,能够是本类型或本类型的集合,都会被执行
使用者能够本身扩充更多的特殊参数类型。
任何只要实现了IHttpActionAttribute、IApiParameterAttribute 、IApiActionFilterAttribute 、IApiReturnAttribute 之一或以上的特性,只要打在接口或参数上,就会获得调用,在调用里实现处理逻辑。
任何实现了IApiParameterable接口的参数值,也会获得调用。
HttpApiClient.Config.UseXmlFormatter(your formatter)
HttpApiClient.Config.UseJsonFormatter(your formatter)
HttpApiClient.Config.UseHttpClientContextProvider(your provider)
你能够本身控制HttpClient的配置与生命周期
继承ApiActionFilterAttribute,能够实现本身的拦截器,做日志、受权什么的均可以;
在子类修改AllowMultiple属性与OrderIndex属性,能够实现特性的排序与是否在接口和方法上重复使用。
https://github.com/xljiulang/WebApiClient
里面有一个demo,借助networksocket,http服务端与客户端都是同一个进程,调试过程很是方便,数据流向一目了然。
最后,若是你看哪一个哪.net 的httpClient有更方便的调用,请@我,我立刻模仿他。