1

我希望将 NServiceBus 集成到现有的 ServiceStack 网络主机中。ServiceStack 目前正在使用内置的 Funq IoC 容器。NServiceBus 已配置(在系统的其他地方)使用 Unity for IoC。

ServiceStack 有一个特性,当它在类上找到接口时,将自动注入 IRequestContext 。IRequiresRequestContextNServiceBus 通过IMutateOutgoingTransportMessages接口为 Message Mutators 提供了类似的功能。

该应用程序是一个多租户应用程序。单个应用程序通过 API 密钥将帐户代码传递给 NServiceBus 处理程序(间接通过在使用 Unity 构造处理程序的构造函数注入时调用的提供程序)。

我的问题出现在 ServiceStack 中。我正在使用请求过滤器将 API 密钥拖出请求标头,我在数据库中查找,然后最终写入IHttpRequest.Items集合:

appHost.RequestFilters.Add((req, res, requestDto) =>
{
    var tenant = tenantRepository.GetByApiKey(
    req.Items.Add("AccountCode", tenant.AccountCode);
}

然后我有一个 NServiceBus 传输消息修改器,它实现了 IRequiresRequestContext 接口,并且这个类与在 AppHost 中注册的 ServiceStack 服务位于同一个程序集中:

public class MessageHeaderMutator : IMutateOutgoingTransportMessages, INeedInitialization, IRequiresRequestContext
{
    #region IRequiresRequestContext Members

    public IRequestContext RequestContext { get; set; }

    #endregion

    #region IMutateOutgoingTransportMessages Members

    public void MutateOutgoing(object[] messages, NServiceBus.TransportMessage transportMessage)
    {
        transportMessage.Headers.Add("AccountCode", RequestContext.Get<IHttpRequest>().Items["AccountCode"].ToString());
    }

    #endregion

    #region INeedInitialization Members

    public void Init()
    {
        Configure.Instance.Configurer.ConfigureComponent<MessageHeaderMutator>(DependencyLifecycle.InstancePerCall);
    }

    #endregion
}

但是,RequestContext 永远不会被注入,并且始终是null. 我的理论是,通过两个单独的框架注入的两个接口注入在某种程度上是冲突的。

HostContext.Items根据此讨论,我有一个解决方法,即改用 ServiceStack ,但我担心这HostContext不是每个请求的集合,因此我最终可能会将数据写入错误的租户。解决方法是:

// app host
appHost.RequestFilters.Add((req, res, requestDto) =>
{
    var accountCode = tenantRepository.GetByApiKey(
    HostContext.Instance.Items.Add("AccountCode", client.AccountCode);
}


// message mutator
public class MessageHeaderMutator : IMutateOutgoingTransportMessages, INeedInitialization
{
    #region IMutateOutgoingTransportMessages Members

    public void MutateOutgoing(object[] messages, NServiceBus.TransportMessage transportMessage)
    {
        var accountCode = HostContext.Instance.Items["AccountCode"].ToString();
        transportMessage.Headers.Add("AccountCode", accountCode);
    }

    #endregion

    #region INeedInitialization Members

    public void Init()
    {
        Configure.Instance.Configurer.ConfigureComponent<MessageHeaderMutator>(DependencyLifecycle.InstancePerCall);
    }

    #endregion
}

因此,我的问题是双重的:

  1. 首先是,为什么IRequiresRequestContext没有正确注入RequestContextMessage mutator,或者有没有办法手动注入 RequestContext
  2. 是否使用 HostContext保险箱来假设它是每个请求
  3. 额外的问题:在同一个项目中使用两个独立的 IoC 容器(NServiceBus 中的 Unity 和 ServiceStack 中的 Funq)是一个非常糟糕的主意吗?让 ServiceStack 使用与 NServiceBus 相同的 Unity IoC 容器会更聪明吗?

PS 这是 NServiceBus 4(撰写本文时为测试版)。

4

2 回答 2

1

您可以通过 AppHostBase.Container 访问 ServiceStack 容器,并按照 Udi 的建议使用它来解析您的对象。

于 2013-06-07T01:09:38.107 回答
1

正是因为您使用了 2 个不同的容器,所以 DI 不能为您在不同容器中注册的对象开箱即用。

您不一定需要对单个容器进行标准化(尽管它可以使您免于一直处理这些问题)。

要继续使用这两个容器,您可以做的是告诉 NServiceBus 容器如何解析 IRequiresRequestContext,如下所示:

public class RequestContextBootstrapper : INeedInitialization
{
   public void Init()
   {
      Configure.Component<IRequiresRequestContext>( /* get object from ServiceStack */ );
   }
}
于 2013-05-21T14:05:56.363 回答