2017-08-13 2 views
0

Contexte: ASP.NET Core App (1.1).Autofac & MassTransit - Registre Consumer ObjectDisposedException

J'essaie de résoudre l'IRepository que j'ai déjà enregistré quand j'ai besoin d'une instance de consommateur, mais il semble que je reçois une ObjectDisposedException.

BusFactoryMethod

J'ai créé une méthode de fabrication de bus automatique est activée quand je l'appelle méthode .Build() du ContainerBuilder.

public IServiceProvider ConfigureServices(IServiceCollection services) 
{ 
    var containerBuilder = new ContainerBuilder(); 
    containerBuilder.RegisterType<EventTypeResolver>().As<IEventTypeResolver>(); 
    containerBuilder.RegisterType<Repository>().As<IRepository>(); 
    containerBuilder.Register(c => EventStoreConnectionFactory.Create()) 
          .As<IEventStoreConnection>(); 
    containerBuilder.Register(BusFactoryMethod).AsSelf().SingleInstance().AutoActivate(); 
    containerBuilder.Populate(services); 
    return new AutofacServiceProvider(containerBuilder.Build()); 
} 

BusFactoryMethod ressemble à ceci:

private IBusControl BusFactoryMethod(IComponentContext componentContext) 
{ 
    var busControl = BusConfigurator.Instance.ConfigureBus((cfg, host) => 
      { 
       cfg.ReceiveEndpoint(host, RabbitMQConstants.UserManagementQueue, e => 
       { 
        e.Consumer(() => new CreateUserCommandConsumer(componentContext.Resolve<IRepository>())); 
       }); 
      }); 
    busControl.Start(); 
    return busControl; 
} 
+1

Vous enregistrez votre 'IRepository' comme dépendance transitoire, mais votre' IBusControl' est singfleton et selon où vous résolvez 'IBusControl', je..e si vous le résolvez quelque part pendant une requête, il est résolu par le conteneur scoped, mais depuis son singleton il g oes au conteneur parent alors que l'IRepository est résolu par le conteneur scoped et éliminé à la fin de la requête, mais 'IBusControl' ne sera pas éliminé car son singleton – Tseng

+0

Donc vous devrez résoudre' IBusControl' lors du démarrage de l'application 'Configurer 'méthode, ou modifier à la fois la durée de vie' IRepository' et 'IBusControl' (probablement pas possible que vous voulez écouter des événements et des messages) – Tseng

+0

Hmmm. Oui, c'est le cas lorsque j'enregistre que BusFactoryMethod avec AutoActivate sera appelé quand je construirai le conteneur. Mais le Consumer/Repository sera là juste pour la durée de vie de la requête. –

Répondre

0

J'ai donc trouvé un paquet MassTransit.AutofacIntegration qui a déjà une méthode RegisterConsumers.

Ensuite, j'ai utilisé la méthode RegisterGeneric d'Autofac afin d'obtenir une durée de vie par message.

containerBuilder.RegisterGeneric(typeof(AutofacConsumerFactory<>)) 
          .WithParameter(new NamedParameter("name", "message")) 
          .As(typeof(IConsumerFactory<>)) 
          .InstancePerLifetimeScope(); 

Et a fini avec les éléments suivants Module:

public class DefaultModule : Autofac.Module 
     { 
      protected override void Load(ContainerBuilder containerBuilder) 
      { 
       containerBuilder.Register(c => new EventTypeResolver(typeof(DefaultModule).GetTypeInfo().Assembly)).As<IEventTypeResolver>(); 
       containerBuilder.Register(c => EventStoreConnectionFactory.Create()) 
           .As<IEventStoreConnection>(); 
       containerBuilder.RegisterType<Repository>().As<IRepository>(); 
       containerBuilder.RegisterConsumers(typeof(DefaultModule).GetTypeInfo().Assembly).AsSelf().AsImplementedInterfaces(); 
       containerBuilder.RegisterGeneric(typeof(AutofacConsumerFactory<>)) 
          .WithParameter(new NamedParameter("name", "message")) 
          .As(typeof(IConsumerFactory<>)) 
          .InstancePerLifetimeScope(); 
       containerBuilder.Register((c) => 
       { 
        var busControl = BusConfigurator.Instance.ConfigureBus((cfg, host) => 
        { 
         ConfigureEndPoints(cfg, host, c); 
        }); 
        busControl.Start(); 
        return busControl; 
       }).SingleInstance().AutoActivate(); 
      } 

      private void ConfigureEndPoints(IRabbitMqBusFactoryConfigurator cfg, IRabbitMqHost host, IComponentContext context) 
      { 
       cfg.ReceiveEndpoint(host, RabbitMQConstants.UserManagementQueue, e => 
       { 
        e.Consumer(context.Resolve<IConsumerFactory<CreateUserCommandConsumer>>()); 
       }); 
      } 
     } 

méthode ConfigureServices ressemble maintenant à ceci:

public IServiceProvider ConfigureServices(IServiceCollection services) 
     { 
      var containerBuilder = new ContainerBuilder(); 
      containerBuilder.RegisterModule<DefaultModule>(); 
      containerBuilder.Populate(services); 
      return new AutofacServiceProvider(containerBuilder.Build()); 
     } 
+1

Vous pourriez être surpris mais l'adaptateur Autofac est décrit dans la documentation http://masstransit-project.com/MassTransit/usage/containers/autofac.html –