J'ai 2 systèmes, un pour publier des messages et d'autres pour les consommer. Les deux utilisent Masstransit (avec RabbitMQ) et sont implémentés en utilisant ASP.Net web api 2 et OWIN (et Autofac comme conteneur IoC). Tout fonctionne correctement si mon client n'a pas de dépendances, mais lorsque j'injecte une dépendance dans mon client, la méthode Consume n'est jamais exécutée (aucune erreur ne se produit lors de l'initialisation).Enregistrer un IConsumer <T> avec dépendance dans Masstransit utilisant Autofac
Ceci est le correspondant Editeur Code:
//Startup.cs
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
IContainer container = null;
var builder = new ContainerBuilder();
builder.Register(context =>
{
var busControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
IRabbitMqHost rabbitMqHost = cfg.Host(new Uri(ConfigurationManager.AppSettings["RabbitMQHost"]), settings =>
{
settings.Username(ConfigurationManager.AppSettings["RabbitMQUser"]);
settings.Password(ConfigurationManager.AppSettings["RabbitMQPassword"]);
});
});
return busControl;
})
.As<IBusControl>()
.As<IBus>()
.SingleInstance();
// Register Web API controllers
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// Resolve dependencies
container = builder.Build();
config.DependencyResolver = AutofacWebApiDependencyResolver(container);
WebApiConfig.Register(config);
SwaggerConfig.Register(config);
app.UseCors(CorsOptions.AllowAll);
// Register the Autofac middleware FIRST.
app.UseAutofacMiddleware(container);
app.UseWebApi(config);
// Starts MassTransit Service bus, and registers stopping of bus on app dispose
var bus = container.Resolve<IBusControl>();
var busHandle = bus.StartAsync();
var properties = new AppProperties(app.Properties);
if (properties.OnAppDisposing != CancellationToken.None)
{
properties.OnAppDisposing.Register(() => busHandle.Result.StopAsync(TimeSpan.FromSeconds(30)));
}
}
}
// Controller
public IHttpActionResult Post()
{
_bus.Publish<IFooMessage>(new
{
Foo = "Foo"
});
return Ok();
}
Et c'est le pertinent Code de la consommation:
// Startup.cs
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
IContainer container = null;
var builder = new ContainerBuilder();
builder.RegisterType<FooService>().As<IFooService>().InstancePerRequest();
builder.RegisterModule<BusModule>();
builder.RegisterModule<ConsumersModule>();
// Register Web API controllers
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// Resolve dependencies
container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
WebApiConfig.Register(config);
SwaggerConfig.Register(config);
app.UseCors(CorsOptions.AllowAll);
// Register the Autofac middleware FIRST.
app.UseAutofacMiddleware(container);
app.UseWebApi(config);
// Starts MassTransit Service bus, and registers stopping of bus on app dispose
var bus = container.Resolve<IBusControl>();
var busHandle = bus.StartAsync();
var properties = new AppProperties(app.Properties);
if (properties.OnAppDisposing != CancellationToken.None)
{
properties.OnAppDisposing.Register(() => busHandle.Result.StopAsync(TimeSpan.FromSeconds(30)));
}
}
}
// BusModule.cs
public class BusModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.Register(context =>
{
var busControl = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
IRabbitMqHost rabbitMqHost = cfg.Host(new Uri(ConfigurationManager.AppSettings["RabbitMQHost"]), settings =>
{
settings.Username(ConfigurationManager.AppSettings["RabbitMQUser"]);
settings.Password(ConfigurationManager.AppSettings["RabbitMQPassword"]);
});
cfg.ReceiveEndpoint(rabbitMqHost, "IP.AgilePoint.queue", ec =>
{
ec.LoadFrom(context);
});
});
return busControl;
})
.SingleInstance()
.As<IBusControl>()
.As<IBus>();
}
}
// ConsumerModule.cs
public class ConsumersModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<FooConsumer>();
}
}
// FooConsumer.cs
public class FooConsumer : IConsumer<IFooMessage>
{
private IFooService _service;
public FooConsumer(IFooService service)
{
_service = service;
}
public Task Consume(ConsumeContext<IFooMessage> context)
{
IFooMessage @event = context.Message;
_service.DoStuff(@event.Foo);
return Task.FromResult(context.Message);
}
}
Notez mon FooConsumer a une dépendance (constructeur) sur IFooService. J'ai suivi Masstransit documentation mais je n'arrive pas à faire marcher ça. Qu'est-ce que je fais mal?
versions Framework:
- Net Framework 4.6.1
- Autofac:
- 3.5.2 Masstransit: 3.5.7
Mise à jour:
code peut être trouvé in this Github repository
L'enregistrement par requête est uniquement applicable lorsque Autofac gère la portée de la demande et ceci est effectué dans le plug-in d'intégration WebAPI. MassTransit n'utilise pas cela. L'enregistrement par défaut est * not singleton *, c'est par dépendance. C'est la bonne portée. MassTransit instancie un consommateur pour chaque message. –