如何基于最顶层的父命名空间注册有条件的服务

本文关键字:命名空间 注册 有条件 服务 何基于 | 更新日期: 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 
{
    .... 
}

这个想法是让ISessionServiceSessionService在基础项目中。然后有不同的项目来实现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));