StructureMap MassTransit问题:检测到双向依赖关系

时间:2018-10-29 13:53:10

标签: dependency-injection rabbitmq azure-service-fabric structuremap masstransit

当尝试使用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.ConsumerMessageFilter 2.<GreenPipes-IFilter<MassTransit-ConsumeContext<TMessage>>-Send>d__4.MoveNext() at MassTransit.Pipeline.Filters.ConsumerMessageFilter 2。>-发送> d__4.MoveNext()   在GreenPipes.Filters.TeeFilter 1.<Send>d__5.MoveNext() at GreenPipes.Filters.OutputPipeFilter 2.d__7.MoveNext()   在GreenPipes.Filters.OutputPipeFilter 2.<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注册,并且为简洁起见,缺少某些代码。

1 个答案:

答案 0 :(得分:0)

您应该使用MassTransit.StructureMap集成库,而不要使用.Consumer(container.GetInstance<T>)来代替.Consumer<T>(container)

这将使用StructureMap范围提供程序,以便使用者工厂为使用者的所有依赖项创建嵌套的生存期范围。您已经在{/ {1}}中使用了构建器/注册,所以应该可以使用。

此外,这也不是连接观察者的方法,至少不是在应该使用的意义上。有一个ConnectObserver方法,应该在启动总线之前调用它。另外,观察者自己没有生存期作用域,但是使用StructureMap作用域提供程序会将IContext添加到ILifetimeScope有效载荷中,可用于在运行时解析依赖项。