天天看點

Asp.Net Core 減少Controller擷取重複注入對象

    在使用Asp.Net Core的時候我們都會用到依賴注入擷取自定義的服務,如果是倉儲的話可能還好,不同的controller需要用到不同的倉儲,通過構造函數注入也算明确了業務關系。可是在使用到日志服務,緩存服務等工具類服務的時候往往會發現在大多數的controller中都要通過構造函數擷取一遍注入服務,是件很麻煩的事。現在的想法是通過建立繼承自Controller的BaseController類,在BaseController擷取到所有的服務,之後其他controller再繼承自BaseController擷取到這些服務。下面來看下實作方式。

使用的是.net core 2.1。

在Startup的ConfigureServices添加HttpContextAccessor服務

services.AddHttpContextAccessor();
           

建立自定義的服務和接口

public interface IMyService
{
    string GetGuId();
}
           
public class MyService : IMyService
{
    private string guid = Guid.NewGuid().ToString();

    public string GetGuId()
    {
        return guid;
    }
}
           

在Startup的ConfigureServices中注冊自定義服務

//services.AddSingleton<IMyService, MyService>();
//services.AddTransient<IMyService, MyService>();
services.AddScoped<IMyService, MyService>();
           

定義靜态類ServiceLocator

public static class ServiceLocator
{
    public static IServiceProvider Instance { get; set; }
}
           

在Startup的Configure為ServiceLocator.Instance指派

ServiceLocator.Instance = app.ApplicationServices;
           

在BaseController的構造方法裡通過ServiceLocator.Instance擷取IHttpContextAccessor,再使用IHttpContextAccessor擷取注冊的自定義服務。這裡不直接使用ServiceLocator.Instance.GetService方法擷取自定義服務是,因為如果使用Scoped方式注冊服務的話這裡擷取服務會報錯。

public class BaseController : Controller
{
    protected IMyService _myService;
    public BaseController()
    {
        var hca = ServiceLocator.Instance.GetService<IHttpContextAccessor>();
        _myService = hca.HttpContext.RequestServices.GetService<IMyService>();
    }
}
           

讓自定義的Controller繼承自BaseController,通過BaseController擷取自定義服務

public IActionResult GetGuId()
{
    return Content(_myService.GetGuId());
}
           

這裡特别感謝 田園裡的蟋蟀 的《ASP.NET Core DI 手動擷取注入對象》

繼續閱讀