如何在netcore下,愉快的使用IServiceProvider


之前一直做dotnet framework開發,依賴注入使用Autofac,Autofac的一般用法是服務啟動時,將用到的接口、實現類名注入進去,

然后在服務其他地方如果使用該類時,直接在Container里面Resolve出來即可。

 

后來使用netcore 2.1,框架本身使用了Microsoft.Extensions.DependencyInjection,是服務啟動時,把需要注入的服務通過

public void ConfigureServices(IServiceCollection services)

實現依賴注入,在服務其他地方通過構造函數把服務實例化出來,然后實現具體方法的調用。

 

期初,因為場景比較簡單,用起來比較舒服,后來隨着業務復雜,就面臨了一些挑戰:

1)在服務的某個方法中,不想通過構造函數,現在想使用已經注入的接口方法,咋辦?

為了解決這個問題,我們引入了IHttpContextAccessor(web服務),在IHttpContextAccessor里面有HttpContext,

在HttpContext里面有個RequestServices就是IServiceProvider類型,里面有我們想要的已經注入的服務:

 public abstract class ControllerBase : Controller
 {
    protected ControllerBase(IMediator mediator, ILogger logger, IHttpContextAccessor accessor)
     {
        var configuration = accessor.HttpContext.RequestServices.GetRequiredService<IConfigurationManager>();
     }
 }

 PS:使用HttpContext里面的RequestServices是有局限的,比如單元測試怎么寫?(其實還是仿web的初始化,本次不討論)

上面的使用HttpContext里面的RequestServices解決了一些問題,但是后來又遇到問題了

2)異步編程,Handler里面處理的邏輯比較耗時,所以我們打算把里面的邏輯抽出來使用異步方式,然后立刻返回結果,

立刻返回結果導致HttpContext.RequestServices變成了null,所以在異步調用邏輯中用到RequestServices的地方全部報錯。

 

根據這個問題,我們在common項目里面增加ServiceLocator類:

public class ServiceLocator
    {
        public static IServiceProvider Services { get; private set; }
        public static void SetServices(IServiceProvider services)
        {
            Services = services;
        }
    }

 然后在 public void ConfigureServices(IServiceCollection services)

 方法里面使用

 // 將注入放在全局變量里維護
 ServiceLocator.SetServices(serviceProvider);

 PS:盡量在該方法的最下面使用這個賦值。

然后在你服務中的其他位置使用它拿到已經注入的接口

  注意:在ServiceLocator里面使用的接口應該都是只讀的實例,這樣就不會產生更新操作,導致線程不安全的問題

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM