我希望将NServiceBus集成到现有的ServiceStack Web主机中。 ServiceStack目前正在使用内置的Funq IoC容器。 NServiceBus已经配置(在系统的其他地方)使用Unity for IoC。
当ServiceStack在类上找到IRequiresRequestContext
接口时,它具有IRequestContext will be automatically injected的功能。 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传输消息mutator,它实现了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
。我的理论是,通过两个独立的框架注入的两个接口注入在某种程度上是冲突的。
我有一个解决方法,即根据this discussion使用ServiceStack HostContext.Items
,但我担心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,或者有inject RequestContext manually方法? HostContext
是否安全,假设每次请求 ?P.S。这是NServiceBus 4(撰写本文时为测试版)。
答案 0 :(得分:1)
正是因为你正在使用2个不同的容器,所以DI对于你来说不适用于在不同容器中注册的对象。
您不一定需要对单个容器进行标准化(尽管它可以帮助您免于处理这些类型的问题)。
继续使用这两个容器可以做的是告诉NServiceBus容器如何解析IRequiresRequestContext,如下所示:
public class RequestContextBootstrapper : INeedInitialization
{
public void Init()
{
Configure.Component<IRequiresRequestContext>( /* get object from ServiceStack */ );
}
}
答案 1 :(得分:1)
您可以通过AppHostBase.Container访问ServiceStack容器,并使用它来解析Udi建议的对象。