使用具有依赖注入的工厂来优化Web请求中的对象创建

问题描述 投票:1回答:1

简而言之,这是我在每个代码库中专业看到的控制器类型:

    //All in One Service interfaces
    public class DiController : ControllerBase
    {
        private readonly IDiService _diService;

        public DiController(IDiService diService)
        {
            _diService = diService;
        }

        [HttpGet]
        public IActionResult GetA()
        {
            return Ok(_diService.GetA());
        }

        [HttpGet]
        public IActionResult GetB()
        {
            return Ok(_diService.GetB());
        }
    }

    //Task-based interfaces 
    public class DiController : ControllerBase
    {
        private readonly IAService _aService;
        private readonly IBService _bService;

        public DiController(IAService aService, IBService bService)
        {
            _aService = aService;
            _bService = bService;
        }

        [HttpGet]
        public IActionResult GetA()
        {
           return Ok(_aService.Handle());
        }

        [HttpGet]
        public IActionResult GetB()
        {
            return Ok(_bService.Handle());
        }
    }

现在为了使帖子保持较小,假设您有一个用于A的存储库和另一个用于B的存储库,供服务使用。这里的每个组件都是Scoped(每个请求都是相同的对象)。不管你选择什么,你最终会遇到这样的情况:

enter image description here

这是基于任务的界面的情况,正如您所看到的,您没有使用服务B,但无论如何都会获得一个实例。在另一种情况下,您将实例化两个存储库。

为了解决这个问题,我使用了像这样的工厂:

1 - 包含容器的抽象类和提供Type实例的属性。

    public interface IGenericFactory<out T>
    {
        T Service { get; }
    }

    public abstract class GenericFactory<T> : IGenericFactory<T> where T : class
    {
        private readonly Container _container;
        public T Service => _container.GetInstance<T>();

        protected GenericFactory(Container container)
        {
            _container = container;
        }
    }

2-要在容器中注册的接口

public interface IAServiceFactory : IGenericFactory<IAService>
{
}

3-要在容器中注册的类

public class AServiceFactory : GenericFactory<IAService>, IAServiceFactory
{
    public AServiceFactory(Container container) : base(container)
    {

    }
}

4-将工厂注册为单身人士,将服务注册为Scoped / Transient(根据用例)。这将是一个示例(在简单​​注入器中)如何完成基于任务的接口控制器的注册:

_container.Register<IAService, AService>(Lifestyle.Scoped);
_container.Register<IBService, BService>(Lifestyle.Scoped);

_container.Register<IAServiceFactory, AServiceFactory>(Lifestyle.Singleton);
_container.Register<IBServiceFactory, BServiceFactory>(Lifestyle.Singleton);

最终产品将是这样的:

enter image description here

A的实例,而不是B.

它是否正确?我一直在你会有十几个服务或存储库的项目中,每次调用只会使用一个。

谢谢。

c# asp.net .net dependency-injection simple-injector
1个回答
1
投票

你可以注入动作:

public IActionResult About([FromServices] IDateTime dateTime)
{
    ViewData["Message"] = $"Current server time: {dateTime.Now}";

    return View();
}

https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/dependency-injection?view=aspnetcore-2.2#action-injection-with-fromservices

© www.soinside.com 2019 - 2024. All rights reserved.