WebApiClient庫支持AOT

1 庫簡介

WebApiClient是開源在github上的一個http客戶端庫,內部基於HttpClient開發,只須要定義c#接口(interface),並打上相關特性,便可異步調用http-api。該庫支持framework4.5+netstandard1.3netcoreapp2.1,包含如下特性:ios

  • 原生的支持面向切面編程;
  • 內置豐富的特性,支持自定義特性;
  • 靈活和Filter、GlobalFilter和IParameterable;
  • 功能強大的序列化工具;
  • 與外部HttpMessageHandler無縫銜接;
  • 獨一無二的請求異常條件重試功能和異常處理鏈式語法功能

2 WebApiClient.JIT

JIT,即Just-in-time,動態(即時)編譯,邊運行邊編譯,WebApiClient.JIT在運行時,在須要的時候使用Emit建立Http請求接口的代理類。c++

2.1 動態代理

[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

2.2 優點和劣勢

優點:不依賴於編譯器,在運行時用到接口的時候,按需默默地爲開發者實現了請求接口的代理類,這些接口的定義能夠在外部程序集,同時編寫接口的語言只要是能編譯爲中間公共語言的就獲得支持。github

劣勢:因爲嚴重依賴於JIT,對於編譯階段就將IL翻譯到平臺本機指令的地方,將沒法獲得支持,好比unity3d、ios或uwp,由於須要在編譯階段將IL再編譯爲平臺本機指令,而動態代理IL在這個時期還不存在,同時編譯器也會禁止代碼裏使用Emit相關Api,由於運行時不會再有JIT的存在。web

3 WebApiClient.AOT

AOT,Ahead Of Time,指運行前編譯,WebApiClient.AOT在編譯階段,就自動插入Http請求接口的代理類IL指令。編程

3.1 編譯時插入代理類IL

這類需求其實是自動幫開發者補充接口實現類的代碼,而後合併到項目一塊兒編譯。考慮到開發語言的衆多,好比c#vb.netc++/clif#等等,並且語言特性也在不斷變化,因此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>

3.2 優點和劣勢

優點:支持的平臺更普遍,在編譯時就能夠靜態檢查接口聲明是否分的符合框架約定。api

劣勢:依賴於編譯器和編譯過程,必須在項目引用nuget包才支持,直接引用WebApiClient.AOT庫開發的話,編譯時不會插入IL代理指令。app

4 如何選擇

若是你不是用於unity3d、ios或uwp這些平臺應用開發,選擇WebApiClient.JIT將比較方便;若是你不肯定將來項目是否也會用於上面這些平臺,就選擇WebApiClient.AOT。不過無論怎麼樣,兩個提供Api是徹底一致,區別只在於你看不到的編譯過程或運行時過程。

相關文章
相關標籤/搜索