Asp.net core 继承上的服务定位器模式与服务聚合工厂
假设我有一个需要大量服务的基类。这个基类有一些派生类Asp.net core 继承上的服务定位器模式与服务聚合工厂,asp.net-core,dependency-injection,Asp.net Core,Dependency Injection,假设我有一个需要大量服务的基类。这个基类有一些派生类 class BaseClass { BaseClass(IServiceA srvA, IServiceB srvB) { ... } } 要使用DI从此基类继承,我需要在派生类中重复构造函数参数: class DerivedClassA { DerivedClassA(IServiceA srvA, IServiceB srvB) : base(srvA, srvB) {} } 当以后基类需要新的依赖项时,我将不得不更改
class BaseClass
{
BaseClass(IServiceA srvA, IServiceB srvB) { ... }
}
要使用DI从此基类继承,我需要在派生类中重复构造函数参数:
class DerivedClassA
{
DerivedClassA(IServiceA srvA, IServiceB srvB) : base(srvA, srvB) {}
}
当以后基类需要新的依赖项时,我将不得不更改基类和派生类。想象一下当有几个派生类时的噩梦
class BaseClass
{
BaseClass(IServiceA srvA, IServiceB srvB) { ... }
}
我做了一些研究,似乎有一个解决方案,即服务聚合工厂(或类似术语):
这样,每次需要向类添加更多服务时,我只需要更改ServiceFactory
,而不需要更改它们
但是还有IServiceProvider
,它是.NETCore中的默认DI容器。所以我可以做到:
class BaseClass
{
public BaseClass(IServiceProvider provider)
{
this._srvA = provider.GetRequiredService<IServiceA>();
this._srvB = provider.GetRequiredService<IServiceB>();
}
}
class DerivedClassA : BaseClass
{
public DerivedClassA(IServiceProvider provider) : base(provider) {}
}
类基类
{
公共基类(IServiceProvider提供程序)
{
这是._srvA=provider.GetRequiredService();
这是._srvB=provider.GetRequiredService();
}
}
类派生ClassA:基类
{
public-DerivedClassA(IServiceProvider提供程序):基本(提供程序){}
}
它看起来与服务聚合工厂一样,但人们说直接使用IServiceProvider
是一种反模式。所以我很困惑。我应该选择哪个选项
假设我有一个需要大量服务的基类。这个基类有一些派生类
class BaseClass
{
BaseClass(IServiceA srvA, IServiceB srvB) { ... }
}
我不在这里看书了,你也应该这么做。这是一个明确的指标,表明您的基类做得太多了。这违反了公司的SRP(单一责任原则)
构造函数注入使得设计缺陷(如实体违规)非常明显,您应该注意它,因为它告诉您,当您的类有太多的责任时(一个试图做太多的类)
首先也是最重要的,您需要思考为什么基类需要这些依赖项,并对此进行更改。
您的问题是抽象的,所以无法告诉您为什么您的类可能需要这么多依赖项
如果您的类
。GetDrives
方法可以枚举硬件设备并扫描其分区,并侦听每个正确格式化的分区,这样调用代码就不必重复
假设您拥有像IMemoryService
、ICpuService
、IDiskService
、INetworkService
这样的服务,并将它们注入到所有基类中。这有很多依赖关系
相反,您可以有一个IComputerServices
接口,该接口允许您访问所有这些由易于使用的API/方法/属性隐藏的服务(即IComputerServices.CopyFileTo
方法,该方法将所有复制操作抽象为一个简单易用的方法,并将其注入到您的服务中。现在,您可以将类似computerServices.CopyFileTo的文件复制到(sourceFile,destinationFile)
如果出现了新的依赖项,例如IDisplayService
,您只需将其添加到facade服务中,它将在您的所有类中可用,这些类也会注入IComputerServices
假设我有一个基类,它需要一组服务,这个基类有一些派生类
class BaseClass
{
BaseClass(IServiceA srvA, IServiceB srvB) { ... }
}
停止阅读这里的内容,你也应该这样做。这是一个明确的指标,表明你的基类做得太多了。这违反了来自的SRP(单一责任原则)
构造函数注入使得设计缺陷(如实体违规)非常明显,您应该注意它,因为它告诉您,当您的类有太多的责任时(一个试图做太多的类)
首先也是最重要的,您需要思考为什么基类需要这些依赖项,并对此进行更改。
您的问题是抽象的,所以无法告诉您为什么您的类可能需要这么多依赖项
如果您的类<强>真正的< /强>需要所有这些依赖关系,请考虑使用一个Futal.外观是另一个类,它隐藏了一个易于使用的接口背后的复杂性和依赖性,从而减少了依赖性的数量.参见Mark Seemann的.
facade不仅仅是一个类,它提供了对其他依赖项的轻松访问(即,一个只有5个表示其他服务的属性的类).facade将尽可能隐藏依赖项,并提供方法来轻松访问其背后的功能,即。GetDrives
方法可以枚举硬件设备并扫描其分区,并侦听每个正确格式化的分区,这样调用代码就不必重复
假设您拥有像IMemoryService
、ICpuService
、IDiskService
、INetworkService
这样的服务,并将它们注入到所有的基类中。这是很多依赖项
相反,您可以有一个IComputerServices
接口,该接口允许您访问所有这些由易于使用的API/方法/属性隐藏的服务(即IComputerServices.CopyFileTo
方法,该方法将所有复制操作抽象为一个简单易用的方法,并将其注入到您的服务中。现在,您可以将类似computerServices.CopyFileTo的文件复制到(sourceFile,destinationFile)
如果出现了新的依赖项,例如IDisplayService
,您只需将其添加到facade服务中,它将在您的所有类中都可用