如何基于最顶层的父命名空间注册有条件的服务
本文关键字:命名空间 注册 有条件 服务 何基于 | 更新日期: 2023-09-27 18:12:28
我有以下类,我在使用 SimpleInjector
解决时遇到问题。
配置接口
Namespace Infrastructure.Base.Interfaces
public interface ILdapConfigService
{
.....
}
会话接口
Namespace Infrastructure.Base.Interfaces
public interface ISessionService
{
LdapConnection GetConnection();
}
会话实施
Namespace Infrastructure.Base.Services
public class SessionService : ISessionService {
ILdapConfigService _ldapConfigService;
public SessionService (ILdapConfigService ldapConfigService)
{
_ldapConfigService = ldapConfigService;
}
public LdapConnection GetConnection()
{
.........
}
}
配置服务实现 1
namespace Infrastructure.Old.Services
public class OldConfigService : ILdapConfigService
{
....
}
配置服务实现 2
namespace Infrastructure.New.Services
public class NewConfigService : ILdapConfigService
{
....
}
这个想法是让ISessionService
和SessionService
在基础项目中。然后有不同的项目来实现LdapConfigService
女巫实现ILdapConfigService
从基础项目。
不同的项目也将具有使用基类中的存储库的服务。
我需要知道如何注册这些接口,或者甚至可以像这样注册吗?
Infrastructure.New.Service.SomeService
使用Infrastructure.Base.Interfaces.IRepository
. Infrastructure.Old.Service.SomeOtherService
使用Infrastructure.Base.Interfaces.IRepository
.
Infrastructure.Base.Repositories.Repository
实现Infrastructure.Base.Interfaces.IRepository
. Infrastructure.Base.Repositories.Repository
使用Infrastructure.Base.Interfaces.ISessionService
.
Infrastructure.Base.Services.SessionService
实现Infrastructure.Base.Interfaces.ISessionService
. Infrastructure.Base.Services.SessionService
使用Infrastructure.Base.Interfaces.ILdapConfigService
.
Infrastructure.New.Services.LdapConfigService
实现Infrastructure.Base.Interfaces.ILdapConfigService
.
Infrastructure.Old.Services.LdapConfigService
实现Infrastructure.Base.Interfaces.ILdapConfigService
.
我怎样才能向Simple Injector
注册此逻辑。我用了RegisterConditional
但这并不完全有效,因为ILdapConfigService
的消费者坐在基地里。
container.RegisterConditional<
ILdapConfigService,
Old.Services.LdapConfigService>(
c => c.Consumer.ImplementationType.Namespace.Contains("Old"));
container.RegisterConditional<
ILdapConfigService,
New.Services.LdapConfigService>(
c => c.Consumer.ImplementationType.Namespace.Contains("New"));
container.Register<ISessionService, SessionService>();
container.Register<ILdapRepository, LdapRepository>();
每个LdapConfigService
都与一个app.config
通信,所有重要信息都加载到其中。
Base 执行整个实现以OpenLdap
,但配置需要注入到SessionService
中,以便它与正确的服务器通信。谁知道抽象会变得如此复杂。
我的设计模式可能有缺陷吗?
我的设计模式可能有缺陷吗?
只要你确定你没有违反 Liskov 替换原则,我就找不到它的任何缺陷,尽管这种设计确实使配置容器变得更加困难。
我认为这里的诀窍是创建两个ISessionService
实现;一个用于New
的东西,一个用于Old
的东西。这允许您根据类型进行区分。这是必需的,因为简单注射器的RegisterConditional
具有仅允许您查看注册的直接消费者类型的限制。您正在有条件地注册ILdapConfigService
,但它总是被注入SessionService
。通过给每个ILdpConfigService
自己的ISessionService
,你可以允许根据ISessionSerice
的消费者来制作条件。
简单注入器的这种限制是故意的,存在是为了防止用户进行无效的配置。例如,如果SessionService
被注册为单例,则它不可能有两个不同的ILdapConfigServices
。
由于创建两个ISessionService
实现是一个"配置技巧",因此您可以简单地将第二个实现定义为组合根的一部分,并从第一个实现继承它。通过这样做,您可以根据类型进行匹配,如下所示:
class NewSessionService : SessionService {
public NewSessionService(ILdabConfigService s) { ... }
}
container.RegisterConditional<ISessionService, SessionService>(
c => c.Consumer.ImplementationType.Namespace.Contains("Old"));
container.RegisterConditional<ILdabConfigServices, Old.LdapConfigService>(
c => c.Consumer.ImplementationType == typeof(SessionService));
container.RegisterConditional<ISessionService, NewSessionService>(
c => c.Consumer.ImplementationType.Namespace.Contains("New"));
container.RegisterConditional<ILdabConfigServices, New.LdapConfigService>(
c => c.Consumer.ImplementationType == typeof(NewSessionService));