当尝试使用MassTransit RabbitMQ和StructureMap快速连续处理多个消息时,出现错误:
检测到双向依赖关系!
这仅适用于消费者,错误如下:
MT-Fault-ExceptionType:StructureMap.Building.StructureMapBuildException MT故障消息:检测到双向依赖关系! 检查下面的StructureMap堆栈跟踪: 1.) Acme.Co.WorkerService.Consumers.SomeCommandConsumer的实例
MT-Fault-StackTrace:位于lambda_method(Closure,IBuildSession,IContext) 在StructureMap.Building.BuildPlan.Build(IBuildSession会话,IContext上下文) 在StructureMap.SessionCache.GetObject(类型pluginType,实例实例,ILifecycle生命周期) 在StructureMap.SessionCache.GetDefault(Type pluginType,IPipelineGraph pipelineGraph) 在StructureMap.BuildSession.GetInstanceT 在MassTransit.Pipeline.ConsumerFactories.DelegateConsumerFactory
1.<Send>d__2
1.MoveNext() 在MassTransit.Pipeline.Filters.ConsumerMessageFilter2.<GreenPipes-IFilter<MassTransit-ConsumeContext<TMessage>>-Send>d__4.MoveNext() at MassTransit.Pipeline.Filters.ConsumerMessageFilter
2。>-发送> d__4.MoveNext() 在GreenPipes.Filters.TeeFilter1.<Send>d__5.MoveNext() at GreenPipes.Filters.OutputPipeFilter
2.d__7.MoveNext() 在GreenPipes.Filters.OutputPipeFilter2.<SendToOutput>d__7.MoveNext() at GreenPipes.Filters.DynamicFilter
1.d__9.MoveNext() 在MassTransit.Pipeline.Filters.DeserializeFilter.d__4.MoveNext() 在GreenPipes.Filters.RescueFilter`2.-Send> d__5.MoveNext()
我看不到任何循环依赖性或双向依赖性,但是我可能遗漏了一些东西。
命令使用者的代码(基本上)是:
public class SomeCommandConsumer : IConsumer<ISomeCommand>
{
private readonly IRepository _repository;
private readonly IAnotherRepository _anotherRepository;
public SomeCommandConsumer(IRepository repository, IAnotherRepository anotherRepository)
{
_repository = repository;
_anotherRepository = anotherRepository;
}
public async Task Consume(ConsumeContext<ISomeCommand> context)
{
try
{
await DoSomeWork(context);
await context.Publish<ISomeProcessCompleteEvent>(new
{
context.Message.ID,
SomeProperty = SomeEnum.SomeValue
});
}
catch (Exception e)
{
HandleException(e);
}
}
}
StructureMap注册有效:
public class WorkflowServiceRegistry : Registry
{
public WorkflowServiceRegistry()
{
var configuration = FabricRuntime.GetActivationContext().GetConfigurationPackageObject(Constants.ServiceFabricConfigurationSection);
var baseUri = configuration.Settings.Sections[Constants.ConfigurationRabbitMqConfigSection].Parameters[Constants.ConfigurationRabbitMqBaseUri].Value;
var username = configuration.Settings.Sections[Constants.ConfigurationRabbitMqConfigSection].Parameters[Constants.ConfigurationRabbitMqUsername].Value;
var password = configuration.Settings.Sections[Constants.ConfigurationRabbitMqConfigSection].Parameters[Constants.ConfigurationRabbitMqPassword].Value;
var connectionString = configuration.Settings.Sections[Constants.ConfigurationDatabaseSection].Parameters[Constants.ConfigurationDatabaseConnectionString].Value;
var dbTimeout = int.Parse(configuration.Settings.Sections[Constants.ConfigurationDatabaseSection].Parameters[Constants.ConfigurationDatabaseTimeout].Value);
For<IAnotherRepository>().Use<AnotherRepository>();
For<IRepository>()
.Use<Repository>()
.Ctor<string>()
.Is(connectionString);
ForConcreteType<SomethingCompleteEventConsumer>()
.Configure
.Ctor<string>("baseUri")
.Is(baseUri);
ForConcreteType<SomeCommandConsumer>();
ForConcreteType<SomethingCompleteEventConsumeObserver>();
For<IBusControl>().Use(container => BusConfigurator.ConfigureBus(
baseUri,
username,
password,
(cfg, host) => cfg.ReceiveEndpoint(host, Constants.ControllerSerivceAnalysisProcessStartQueue, SomeCommandQueueConfiguration(container)),
(cfg, host) => cfg.ReceiveEndpoint(host, Constants.ControllerSerivceActionServiceCompleteQueue, SomethingCompleteEventQueueConfiguration(container))
));
For<ICommunicationListener>().Use<MassTransitListener>();
}
private static Action<IRabbitMqReceiveEndpointConfigurator> SomeCommandQueueConfiguration(IContext container)
{
return e =>
{
e.Consumer(container.GetInstance<SomeCommandConsumer>);
};
}
private static Action<IRabbitMqReceiveEndpointConfigurator> SomethingCompleteEventQueueConfiguration(IContext container)
{
return e =>
{
e.Consumer(container.GetInstance<SomethingCompleteEventConsumer>);
e.Observer(container.GetInstance<SomethingCompleteEventConsumeObserver>());
};
}
}
只是想知道这是否是某人以前见过的东西?
请注意,该代码是服务结构解决方案的一部分,每个服务都有它自己的相似的“引导程序”,即为StructureMap注册,并且为简洁起见,缺少某些代码。
答案 0 :(得分:0)
您应该使用MassTransit.StructureMap集成库,而不要使用.Consumer(container.GetInstance<T>)
来代替.Consumer<T>(container)
。
这将使用StructureMap范围提供程序,以便使用者工厂为使用者的所有依赖项创建嵌套的生存期范围。您已经在{/ {1}}中使用了构建器/注册,所以应该可以使用。
此外,这也不是连接观察者的方法,至少不是在应该使用的意义上。有一个ConnectObserver方法,应该在启动总线之前调用它。另外,观察者自己没有生存期作用域,但是使用StructureMap作用域提供程序会将IContext
添加到ILifetimeScope
有效载荷中,可用于在运行时解析依赖项。