How to configure services based on request in ASP.NET Core

后端 未结 3 2129
一个人的身影
一个人的身影 2021-02-09 02:33

In ASP.NET Core we can register all dependencies during start up, which executed when application starts. Then registered dependencies will be injected in controller constructor

3条回答
  •  梦如初夏
    2021-02-09 02:45

    I'm afraid you can not directly acheive the goal via simple dependency injection , as the the dependency injection configured at Startup stage , in other words , all services and implementions has been configured before a request comming .

    However , you can inject a Create Service delegate so that can we create the required service implemention instance in runtime .

    For instance , if we have a IReportFactory Interface and two implementions as blew :

    public interface IReportFactory
    {
        object Create();
    }
    
    public class ReportFactory1 : IReportFactory
    {
        public object Create()
        {
            return new { F = 1, };
        }
    }
    public class ReportFactory2 : IReportFactory {
        public object Create()
        {
            return new { F = 2, }; 
        }
    }
    

    As we want to get the required implemention in future , we need to register the Implementions first .

    services.AddScoped();
    services.AddScoped();
    

    and here's where the magic happens :

    1. We don't register a IReportFactory
    2. We just add a Func instead , which is a CreateReportFactoryDelegate

      public delegate IReportFactory CreateReportFactoryDelegate(Microsoft.AspNetCore.Http.HttpContext context);

    We need add the CreateReportFactoryDelegate to servies too.

    services.AddScoped(sp => {
        // return the required implemention service by the context;
        return context => {
            // now we have the http context ,
            // we can decide which factory implemention should be returned;
            // ...
            if (context.Request.Path.ToString().Contains("factory1")) {
                return sp.GetRequiredService();
            }
            return sp.GetRequiredService();
        };
    });
    

    Now , we can inject a CreateReportFactoryDelegate into controller :

    public class HomeController : Controller
    {
        private CreateReportFactoryDelegate _createReportFactoryDelegate;
    
        public HomeController(CreateReportFactoryDelegate createDelegate) {
            this._createReportFactoryDelegate = createDelegate;
            // ...
        }
    
        public async Task CacheGetOrCreateAsync() {
    
            IReportFactory reportFactory = this._createReportFactoryDelegate(this.HttpContext);
            var x=reportFactory.Create();
    
            // ...
            return View("Cache", cacheEntry);
        }
    }
    

提交回复
热议问题