使用工厂来解决依赖关系

3
我们有一个使用autofac的网站解决方案。现在我们希望在Windows服务/控制台应用程序中重复使用某些内容,但这些内容只在从企业总线接收到消息时才可用。 我有以下服务需要重复使用:
public SettingsService : ISettingsService {
    public readonly ITenantIdentifer _tenantIdentifier
    public SettingsService (ITenantIdentifier tenantIdentifier) {
       this._tenantIdentifier =tenantIdentifier; 
    }
    // do other stuff
}

当前的工作设置

对于WebContext,ITenantIdentifier仅使用builder.RegisterType<WebTenantIdentifier>().As<ITenantIdentifier>();在WebApplication中注册。一切正常。

我们的企业总线

企业总线无法解析ITenantIdentifier,直到消息可用。因此,我们创建了一个MessageTenantIdentifier并注册了一个工厂。

 public class MessageTenantIdentifier : ITenantIdentifier
 {
    public delegate MessageTenantIdentifier Factory(int tenantId);
public MessageTenantIdentifier(int tenantId, IOtherDependency stuff)
    {
        _tenantId = tenantId;
        // ...
    }
}

// somewhere else the this is registered     
builder.RegisterType<MessageTenantIdentifier >().As<ITenantIdentifier>().AsSelf();
builder.RegisterGeneratedFactory<MessageTenantIdentifier.Factory>();

问题 工厂只能在处理消息时使用。

public class MsgTypeHandler : IHandleMessages<MsgType>
{
    public MsgTypeHandler(ISettingsService settingsService, MessageTenantIdentifier factory) { ...}
    public async Task Handle(MsgType message)
    {
        var tenantId = message.TenantId;
        // THIS IS THE MOMENT I CAN CONFIGURE THE MessageTenantIdentifier
        var tenantIdentifier = factory.Invoke(tenantId);

        // but this factory is not used against the ISettingsService.  The service to be reused.  <== THE REAL PROBLEM
    }
}

问题:

那么,我该如何解决这个问题?例如,我应该如何设置服务总线中MessageTenantIdentifier的注册? 还是我的依赖项设置有问题?

1个回答

2
如果 MsgTypeHandler 类需要一个 ISettingsService ,但是整个对象图无法解析直到租户ID可用,这意味着 MsgTypeHandler 组合根。这没问题,但这意味着这是您解决整个对象图的地方,因此不要在这里注入单个服务;而是注入所需的工厂:
public class MsgTypeHandler : IHandleMessages<MsgType>
{
    public MsgTypeHandler(ISettingsServiceFactory factory) {...}

    public async Task Handle(MsgType message)
    {
        var tenantId = message.TenantId;
        ISettingsService svc = this.factory.Create(tenantId);

        // User svc here...
    }
}

好的,所以我必须编写自己的工厂方法,因为在这种情况下组合根不能依赖于 DI 框架。 (仍然想知道 autofac 是否没有解决此问题的方法)... - dampee
@dampee 你可以用不同的方式编写工厂,包括让你的 DI 容器处理细节。 - Mark Seemann
我明白了。我真的需要读一本关于这个主题的书。你的书还是一个好的参考,或者你有其他建议吗? - dampee
1
@dampee,我仍然建议使用我的方法;它是有意编写成尽可能具有时间性的。 - Mark Seemann

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接