我正在开发一个 ASP.NET Web API 2 应用程序,它具有以下层:
- Controller
- 服务(接口(interface)/实现)
- 存储库(接口(interface)/实现)
我的几乎所有 Controller 类都共享大约 4 个服务类,这些类是通过构造函数注入(inject)的,在所有 Controller 中如下所示:
public Controller1(
IService1 FirstService,
IService2 SecondService,
IService3 ThirdService,
IService4 FourthService){}
这意味着如果我有 10 个 Controller ,那么我必须通过构造函数分别注入(inject)所有 Controller 中的每个 Service 类,这对我来说似乎是一种开销。
现在,我有一个 BaseApiController 类,它是所有 Controller 类的父类。我正在考虑创建一个 Aotofac AggregateService 接口(interface)并将其注入(inject)基类中。该 AggregateService 类将把所有这些共享 Service 类公开为属性,如下所示:
public interface IAggregateService
{
IService1 FirstService {get;}
IService2 SecondService {get;}
IService3 ThirdService {get;}
IService4 FourthService {get;}
}
然后在 BaseApiController 类中执行此操作:
protected readonly IAggregateService aggregateService;
public BaseApiController(IAggregateService aggregateService)
{
this.aggregateService = aggregateService;
}
并且,在所有 Controller 类中执行此操作:
public Controller1(
IAggregateService aggregateService)
: base(aggregateService){}
最后,在注册依赖项时执行此操作:
containerBuilder.RegisterAggregateService<IAggregateService>();
这是处理我在开始时解释的问题的好方法吗?另外,注册所有共享服务的理想方式应该是什么?例如SingleInstance 或 InstancePerRequest 或其他任何东西,请记住,所有这些都可以通过执行 aggregateService.XService 在每个 Controller 中访问,其中 X 可以是 First、Second、Third 或 Fourth。
最佳答案
实际上,这个解决方案在更简单的场景中工作得很好,我有时用它来简化代码。
但是,您应该注意:
- 它往往会隐藏相关类的依赖关系。
- 如果您想将特定范围规则应用于某些依赖项,这可能会带来挑战。
- 如果您打算模拟或提供特定服务的替代实现,那么自然也有必要模拟聚合服务。
另请参阅:http://blog.ploeh.dk/2010/02/03/ServiceLocatorisanAnti-Pattern/
关于单例:不要使用单例,除非你有充分的理由来维护状态 - 例如如果服务代表缓存。创建新的服务对象实例是为了防止错误和线程问题而进行强隔离所付出的廉价代价。当然,不要使聚合成为单例,因为它会捕获其他服务的单个实例,即使它们没有安全地设计为这样运行。
关于c# - 使用 Autofac 聚合服务来共享依赖项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49606301/