我希望将 NServiceBus 集成到现有的 ServiceStack 网络主机中。ServiceStack 目前正在使用内置的 Funq IoC 容器。NServiceBus 已配置(在系统的其他地方)使用 Unity for IoC。
ServiceStack 有一个特性,当它在类上找到接口时,将自动注入 IRequestContext 。IRequiresRequestContext
NServiceBus 通过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
}
因此,我的问题是双重的:
- 首先是,为什么
IRequiresRequestContext
没有正确注入RequestContext
Message mutator,或者有没有办法手动注入 RequestContext? - 是否使用
HostContext
保险箱来假设它是每个请求? - 额外的问题:在同一个项目中使用两个独立的 IoC 容器(NServiceBus 中的 Unity 和 ServiceStack 中的 Funq)是一个非常糟糕的主意吗?让 ServiceStack 使用与 NServiceBus 相同的 Unity IoC 容器会更聪明吗?
PS 这是 NServiceBus 4(撰写本文时为测试版)。