時間飛快,轉眼半年,碌碌無爲,眼下就要三十而立,回想三年前的今天,我將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有更方便的調用,請@我,我立刻模仿他。