WebApiClient是开源在github上的一个http客户端库,内部基于HttpClient开发,只须要定义c#接口(interface),并打上相关特性,便可异步调用http-api。该库支持framework4.5+
、netstandard1.3
、netcoreapp2.1
,包含如下特性:ios
JIT,即Just-in-time,动态(即时)编译,边运行边编译,WebApiClient.JIT在运行时,在须要的时候使用Emit建立Http请求接口的代理类。c++
[HttpHost("http://www.webapiclient.com")] public interface IMyWebApi : IHttpApi { // GET webapi/user?account=laojiu // Return 原始string内容 [HttpGet("/webapi/user")] ITask<string> GetUserByAccountAsync(string account); // POST webapi/user // Body Account=laojiu&password=123456 // Return json或xml内容 [HttpPost("/webapi/user")] ITask<UserInfo> UpdateUserWithFormAsync([FormContent] UserInfo user); }
例如,开发者定义了如上请求接口,在调用到 HttpApiClient.Create<IMyWebApi>()
时,才会自动建立一个动态模块,动态模块里定义一个实现了IMyWebApi接口的类型,使用IL实现接口的方法,最后实例化并返回此类型的实例,这些过程,都离不开Emit和JIT。git
优点:不依赖于编译器,在运行时用到接口的时候,按需默默地为开发者实现了请求接口的代理类,这些接口的定义能够在外部程序集,同时编写接口的语言只要是能编译为中间公共语言的就获得支持。github
劣势:因为严重依赖于JIT,对于编译阶段就将IL翻译到平台本机指令的地方,将没法获得支持,好比unity3d、ios或uwp,由于须要在编译阶段将IL再编译为平台本机指令,而动态代理IL在这个时期还不存在,同时编译器也会禁止代码里使用Emit相关Api,由于运行时不会再有JIT的存在。web
AOT,Ahead Of Time,指运行前编译,WebApiClient.AOT在编译阶段,就自动插入Http请求接口的代理类IL指令。编程
这类需求其实是自动帮开发者补充接口实现类的代码,而后合并到项目一块儿编译。考虑到开发语言的众多,好比c#
、vb.net
、c++/cli
和f#
等等,并且语言特性也在不断变化,因此WebApiClient没有从代码语法分析和自动补充接口实现类代码这个角度来解决这个问题,而是在编译过程当中,等待输出程序集以后,再往程序集文件里写入代理类的IL代码,这样就能够规避上层编程语言的语法分析难题。json
.net的编译过程,实际上为msbuild的一系列任务组合完成,咱们的项目文件.csproj,实际上msbuild脚本,WebApiClient须要作的是,给msbuild增长一个自定义的任务,用于在完成CoreCompile任务以后,使用mono.cecli修改编译获得的程序集,插入代理类的IL。c#
<?xml version="1.0" encoding="utf-16"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <Runtime Condition="'$(MSBuildRuntimeType)' == 'Core'">netcoreapp1.0</Runtime> <Runtime Condition="'$(MSBuildRuntimeType)' != 'Core'">net45</Runtime> <TaskAssembly>$(MSBuildThisFileDirectory)..\BuildTask\$(Runtime)\WebApiClient.AOT.Task.dll</TaskAssembly> <TargetAssembly>$(MSBuildProjectDirectory)\$(IntermediateOutputPath)$(TargetFileName)</TargetAssembly> </PropertyGroup> <UsingTask TaskName="WebApiClient.AOT.Task.ProxyTask" AssemblyFile="$(TaskAssembly)" /> <Target Name="BuildProxy" AfterTargets="CoreCompile" DependsOnTargets="ResolveProjectReferences;ResolveAssemblyReferences"> <Message Text="BuildProxy: $(TargetAssembly)" Importance="high" /> <WebApiClient.AOT.Task.ProxyTask TargetAssembly="$(TargetAssembly)" References="@(_ResolveAssemblyReferenceResolvedFiles)" /> </Target> </Project>
优点:支持的平台更普遍,在编译时就能够静态检查接口声明是否分的符合框架约定。api
劣势:依赖于编译器和编译过程,必须在项目引用nuget包才支持,直接引用WebApiClient.AOT库开发的话,编译时不会插入IL代理指令。app
若是你不是用于unity3d、ios或uwp这些平台应用开发,选择WebApiClient.JIT将比较方便;若是你不肯定将来项目是否也会用于上面这些平台,就选择WebApiClient.AOT。不过无论怎么样,两个提供Api是彻底一致,区别只在于你看不到的编译过程或运行时过程。