谈谈.NET Core IServiceProvider
【導讀】最近重構部分代碼,因歷史原因在靜態類中需使用注入實例,構造函數注入則不再可取,此時只能構造全局IServiceProvider,所以本文稍微分析下IServiceProvider
要構造全局使用IServiceProvider,我們都知道不能在ConfigureServices方法中直接調用BuildServideProvider而獲取,會提示引起額外的復制等等問題,這里就不用多說 。
構造全局IServiceProvider
首先我們給出對應接口以及具體實現
public?interface?IHelloService {void?SayHello(); }public?class?HelloService?:?IHelloService {public?void?SayHello(){Console.WriteLine("Hello");} }接著我們將其注入為單例形式
最后我們在Configure方法中獲取注入實例并調用實例方法,如下:
var?serviceProvider?=?app.ApplicationServices;var?service?=?serviceProvider.GetRequiredService<IHelloService>(); service.SayHello();看上述調用結果,沒有任何毛病,接下來我們將其注入生命周期修改為Scope看看
此時將拋出如上異常,這里我將具體詳細信息給出,如下:
Cannot?resolve?scoped?service?'...'?from?root?provider
要是我們將生命周期修改為Transient,那么結果和Singleton一樣可正常調用。看到上述異常信息,網上部分資料并沒有說明根本原因,只是給出如下解決方案
serviceCollection.BuildServiceProvider(validateScopes:?false);接下來我們依然保持上述生命周期Scope不變,我們在Configure方法中傳入IServiceProvider參數,結果會怎樣呢?
此時我們將發現結果卻能正常調用,并不會如上述使用屬性而拋出異常,這二者到底有何區別?
依稀記得在使用.NET Core 2.x版本時也遇到過這問題,當時也是想都沒想,直接進行如上配置大方的解決了問題。那么為何進行如上設置就可以了呢?拋異常的根本原因在哪里?
這是因為通過屬性獲取的是根部的IServiceProvider即(root IServiceProvider),而上述以方法參數傳入的則是根部的孩子(child of the root)。
通過看這一塊源碼可通過如下代碼來證明參數所傳入的IServiceProvider的根部就是app.ApplicationServices
如下為上述類截圖源碼,由于上述類屬于程序集內并未對外暴露,所以想要驗證的童鞋可能只能下載依賴注入這塊源碼去驗證才可
分析到這里,想必我們已經明了,只能通過IServiceProvider子級才能解析注入的Scope實例,因此要從根本上解決通過屬性去獲取到注入Scope實例,我們還需手動創建子級才可,如下:
?????屬性獲取的是根部的IServiceProvider即(root IServiceProvider),而以方法參數傳入的則是根部的孩子(child of the root)。
?????屬性需創建子級IServiceProvider才可解析Scope服務
總結
以上是生活随笔為你收集整理的谈谈.NET Core IServiceProvider的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一个.NET Core下的开源插件框架P
- 下一篇: 使用 Xunit.DependencyI