简而言之,这是我在每个代码库中专业看到的控制器类型:
//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(每个请求都是相同的对象)。不管你选择什么,你最终会遇到这样的情况:
这是基于任务的界面的情况,正如您所看到的,您没有使用服务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);
最终产品将是这样的:
A的实例,而不是B.
它是否正确?我一直在你会有十几个服务或存储库的项目中,每次调用只会使用一个。
谢谢。
你可以注入动作:
public IActionResult About([FromServices] IDateTime dateTime)
{
ViewData["Message"] = $"Current server time: {dateTime.Now}";
return View();
}