[英]Inject different implementations into same interface then pick up right implementation in right project / assembly
We have 2 OpenLdap
servers. 我们有2个OpenLdap
服务器。 One is the latest out of the box version. 一个是最新的开箱即用版本。 The other one is an older heavily customized version. 另一个是较旧的高度定制版本。
Both implementations really follows a similar logic. 两种实现确实遵循相似的逻辑。 Take the connection for example. 以连接为例。
Here is the interface 这是界面
namespace Infrastructure.Interfaces
{
public interface ISessionService
{
LdapConnection GetConnection();
}
}
Each of the implementations will make use of this interface to get a connection. 每个实现都将使用此接口来获得连接。
New Server 新服务器
namespace Infrastructure.NewLdap.Service
{
public class SessionService : ISessionService
{
LdapConnection GetConnection()
{
.....
}
}
}
Old Server 旧服务器
namespace Infrastructure.OldLdap.Service
{
public class SessionService : ISessionService
{
LdapConnection GetConnection()
{
.....
}
}
}
Each of the implementations are in different Projects. 每个实现都在不同的项目中。 Each project will have a different app.config
with the right credentials etc. Along with this there is a IConfigService
which will have all the credentials etc loaded into it from the app.config
. 每个项目都有一个带有正确凭据等的不同app.config
。与此同时,还有一个IConfigService
,它将从app.config
加载所有凭据等。
namespace Infrastructure.Interfaces
{
public interface IConfigService
{
string ServerAddress { get; }
...
...
}
}
Again each project will have its own implementation of this. 同样,每个项目都将对此有自己的实现。
The repositories in each project will be different, because of the way we access data in each of the servers. 每个项目中的存储库都会有所不同,因为我们访问每个服务器中数据的方式不同。 The old server will be used to query only so we are using it to import users into the new server. 旧服务器将仅用于查询,因此我们正在使用它将用户导入新服务器。
How would I use Simple Injector
to inject these services into the same interface but depending on which repository is used, the right implementation will be pulled in? 我将如何使用Simple Injector
将这些服务注入同一接口,但是根据所使用的存储库,将引入正确的实现? If that makes sense? 那有道理吗?
Infrastructure.OldLdap.SomeRepo
Use Interfaces.ISessionService
Registered with OldLdap.Service.SessionService
Infrastructure.OldLdap.SomeRepo
使用Interfaces.ISessionService
向OldLdap.Service.SessionService
注册 Infrastructure.NewLdap.SomeOtherRepo
Use Interfaces.ISessionService
Registered with NewLdap.Service.SessionService
向NewLdap.Service.SessionService
注册的Infrastructure.NewLdap.SomeOtherRepo
使用Interfaces.ISessionService
NewLdap.Service.SessionService
Is this even possible, Also does this break the Liskov Substitution Principle
. 这甚至可能,这也打破了Liskov Substitution Principle
。
Am I better to write each implementation as it's own thing? 因为每个实现都是我自己编写的,所以更好吗? If so, won't this break the DRY
principle? 如果是这样,这不会违反DRY
原则吗?
Hope this is not to broad, thank you in advance. 希望这不会广泛,在此先谢谢您。
Also does this break the Liskov Substitution Principle. 这也违反了《里斯科夫替代原则》。
Whether or not you break the LSP depends on how the SessionService
classes behave. 是否断开LSP取决于SessionService
类的行为。 You should always ask yourself: "What will happen if I swap the implementations?" 您应该经常问自己:“如果交换实现,将会发生什么?” If injecting the Oldldap
into the NewRepo
causes the NewRepo
to fail at runtime, you are violating the LSP, which is basically telling you your design is wrong. 如果将Oldldap
注入NewRepo
导致NewRepo
在运行时失败,则说明您违反了LSP,这基本上是在告诉您您的设计是错误的。 If on the other hand the NewRepo
keeps functioning correctly, because both the Oldldap
and Newldap
behave contractually the same, you're fine. 另一方面,如果NewRepo
保持正常运行,因为Oldldap
和Newldap
合同行为相同,那么您就可以了。 So does the repository care about its implementation, or do only you care. 存储库也关心它的实现,还是只关心您。 Note that if the Oldldap
performs too slow for NewRepo
, that is probably not a violation of LSP. 请注意,如果Oldldap
执行过慢NewRepo
,这可能是不违反LSP的。 In that case only you care (or probably your customer, because of non-functional requirements). 在那种情况下,只有您在乎(或者可能是您的客户,因为非功能性要求)。
The solution to LSP violations is always quite easy: give each implementation its own interface. 违反LSP的解决方案总是很容易的:为每个实现提供自己的接口。 Developers tend to have problems with this, because both abstractions seem exact duplicates of each other and making 'a copy' seems to violate DRY. 开发人员往往对此有问题,因为两个抽象看起来都是彼此完全相同的副本,并且制作“副本”似乎违反了DRY。 But appearances are deceptive; 但是,外表是欺骗性的。 although they have the same members, they have a different, incompatible, contract. 尽管它们具有相同的成员,但是它们具有不同的,不兼容的合同。
But in case you are not violating LSP, keeping that single interface is fine (according to the LSP). 但是,如果您没有违反LSP,则保持该单一接口正常(根据LSP)。 You can make multiple contextual registrations with Simple Injector 3 using RegisterConditional
as follows: 您可以使用RegisterConditional
使用Simple Injector 3进行多个上下文RegisterConditional
,如下所示:
container.RegisterConditional<ISessionService,
Infrastructure.OldLdap.Service.SessionService>(
c => c.Consumer.ImplementationType.Namespace.Contains("Oldldap"));
container.RegisterConditional<ISessionService,
Infrastructure.NewLdap.Service.SessionService>(
c => c.Consumer.ImplementationType.Namespace.Contains("Newldap"));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.