前言 上一篇文章我們講了怎麼使用 NET.AutoApi 這個組件來動態生成webapi介面,讓我們不需要創建控制器去轉發業務層代碼。這篇文章主要是講解NET.AutoApi 底層是怎麼實現動態生成webapi介面 我們回顧下- NET.AutoApi 最終的效果 NET.AutoApi內部原理 其 ...
前言
上一篇文章我們講了怎麼使用 NET.AutoApi
這個組件來動態生成webapi介面,讓我們不需要創建控制器去轉發業務層代碼。這篇文章主要是講解NET.AutoApi
底層是怎麼實現動態生成webapi介面
我們回顧下- NET.AutoApi
最終的效果
NET.AutoApi內部原理
其實NET.AutoApi內部是藉助於mvc拋出來的擴展,進行動態配置webapi的,主要有以下這麼幾個地方
- 將當前程式集添加進ApplicationPartManager類中的ApplicationParts集合中
- 增加ApplicationModelConvention處理ApplicationModel,動態增加路由特性等
NET.AutoApi原理之源碼淺析詳解
其實NET.AutoApi 是基於 AspNet Mvc Core 的
builder.Services.AddControllers();
和app.MapControllers();
去做的,微軟留下了很多支持自定義擴展的地方,所以我們看下這兩個方法中它幹了些啥。註意:我這邊只挑出NET.AutoApi
中所用到的地方說,畢竟 mvc 的源碼很長
builder.Services.AddControllers();
- 第一點,
AddControllers
內部會調用AddMvcCore
。做的第一件事就是將當前啟動程式集放到ApplicationPartManager
類的ApplicationParts
集合中
-
第二點:上圖中的
ConfigureDefaultFeatureProviders
方法,請記住ApplicationPartManager對象中的這個集合FeatureProviders
,以及這個類ControllerFeatureProvider
註意FeatureProviders集合以及ControllerFeatureProvider,這個ControllerFeatureProvider類的作用是:用於找出(過濾)程式集(ApplicationParts集合)中的控制器類(PS:那麼我們只需要把我們的程式集添加到ApplicationParts集合中,然後增加一個FeatureProvider,可以將任何程式集中的類型,都添加為控制器類)
-
第三點,添加一些若幹服務註入,我這邊只列舉出我們所需的,大家有興趣自己去看源碼
- MvcOptions:這個配置內有一個我們需要的東西,
Conventions
集合屬性,
這個
IApplicationModelConvention
集合,可以對控制器類型和方法進行操作,賦予它路由及其它信息 - MvcOptions:這個配置內有一個我們需要的東西,
- services.TryAddSingleton
():這個類很重要,它是將我們的控制器類型,轉換成 ApplicationModel
ApplicationModel內包含了,每個控制器類的元屬性(方法,路由信息、過濾器、特性標簽等等),大家註意:這裡會調用MvcOptions中的Conventions集合的Apply方法,我們可以自行添加Convention,這個時候可以將任何類都動態賦予路由等元屬性,那麼我們可以給一些原本不是控制器類型的類,添加路由信息,讓他具備控制器的特性。
services.TryAddSingleton<IActionDescriptorCollectionProvider, DefaultActionDescriptorCollectionProvider>();
和Transient<IActionDescriptorProvider, ControllerActionDescriptorProvider>()
這個
DefaultActionDescriptorCollectionProvider
的類做了兩個事,
- 他會調用ApplicationModelFactory類的方法,將控制器類集合,轉換成ApplicationModel。
- 然後又將ApplicationModel轉換成ActionDescriptor集合
app.MapControllers();
- 開啟一個訂閱
- 將控制器方法,轉換成Endpoint對象(內部是一個RequestDelegate)
- ControllerActionInvoker內部,這個類內部包含了整個請求流程處理,感興趣的朋友自己去看源碼,我這就不繞進去了。