webentwicklung-frage-antwort-db.com.de

MassTransit und .NET Core DI - Wie löst man Abhängigkeiten mit parameterlosem Konstruktor auf?

Ich arbeite an der App mit .NET Core 2 und MassTransit 4 (dev).

Mass Transit erfordert einen parameterlosen Konstruktor für Verbraucher. Ich brauche z. logger, dbContext etc in meinen Konsumenten und ich würde gerne native DI aus .NET Core verwenden, damit ich nicht lieber Autofac etc hinzufügen müsste (wenn möglich?). Es tritt das Problem auf, wenn .NET Core DI meine deps nicht einfügen kann, da mein Consumer mit parameterlosem Konstruktor erstellt wird.

Gibt es eine Möglichkeit, Abhängigkeiten mit nativem Netzkern-DI aufzulösen, während der parameterlose Konstruktor OR mit Endpunkten von MassTransit deklariert werden kann, die andere als Standardfunktionen ermöglichen:

sbc.ReceiveEndpoint(Host, Configuration["QueueName"], 
                    e => { e.Consumer<MyAwesomeConsumer>();});

Ich habe versucht:

// =========== MASS TRANSIT ===============
            var serviceProvider = services.BuildServiceProvider();
            services.AddSingleton<MyAwesomeConsumer, MyAwesomeConsumer>();
            var bus = Bus.Factory.CreateUsingRabbitMq(sbc =>
            {
                var Host = sbc.Host(new Uri("rabbitmq://localhost"), h =>
                {
                    h.Username("guest");
                    h.Password("guest");
                });

                sbc.ReceiveEndpoint(Host, Configuration["QueueName"],
                    e =>
                    {
                        e.Consumer(typeof(MyAwesomeConsumer), serviceProvider.GetService);
                    });
            });

Die Anwendung wird angehoben, aber sobald die erste Nachricht eingeht, erhalte ich eine Fehlermeldung: MassTransit.ConsumerException: Unable to resolve consumer type 'AuthService.Integrations.MyAwesomeConsumer'.

Ich freue mich über jede Hilfe. Ich hoffe, es ist klar, worum ich frage.

7
M U

Wenn Sie den Container Microsoft.Extensions.DependencyInjection verwenden (der Standard bei ASP.NET Core), benötigen Sie das Paket MassTransit.Extensions.DependencyInjection für MassTransit. Beachten Sie, dass das Paket derzeit nur als Vorabversion verfügbar ist und außerdem eine Vorabversion von MassTransit erfordert. Darüber hinaus ist das neue Paket Teil von einer massiven Migration für .NET Standard , die immer noch nicht abgeschlossen ist. Sie sollten daher wahrscheinlich etwas vorsichtig sein, da es wahrscheinlich bis zum Final einige bewegliche Teile geben wird Veröffentlichung.

Da das Paket nicht offiziell veröffentlicht wurde, ist noch keine Dokumentation darüber enthalten. Aber aus dem Blick auf die Pull-Anfrage, die ihn eingeführt hat und die aktuelle Quelle , denke ich, was Sie tun müssen, ist folgendes:

In Startup.ConfigureServices müssen Sie MassTransit hinzufügen, genau wie Sie andere Dienste hinzufügen würden:

services.AddMassTransit(c =>
{
    c.AddConsumer<MyConsumer>();
    c.AddConsumer<MyOtherConsumer>();

    // or sagas
    c.AddSaga<MySaga>();
});

// you still need to register the consumers/sagas
services.AddScoped<MyConsumer>();
services.AddScoped<MyOtherConsumer>();
services.AddSingleton<ISagaRepository<MySaga>, InMemorySagaRepository<MySaga>>();

In der Konfigurationsaktion müssen Sie Ihre Verbraucher und Sagas registrieren, damit MassTransit sie später ordnungsgemäß auflösen kann.

Dann würden Sie in Ihrer Buskonfiguration LoadFrom beim Dienstanbieter anrufen:

sbc.ReceiveEndpoint(Host, Configuration["QueueName"], e =>
{
    e.LoadFrom(serviceProvider);
});

In Bezug auf where sollten Sie dies tun (auch um Zugriff auf den Dienstanbieter zu erhalten). Ich würde Ihnen vorschlagen, dies in Ihrer StartupConfigure-Methode zu tun. Die Methode kann jede Abhängigkeit als Argument annehmen, sodass Sie den Diensteanbieter dort einfach einfügen können:

public void Configure(IApplicationBuilder app, IServiceProvider serviceProvider, IApplicationLifetime applicationLifetime)
{
    var bus = Bus.Factory.CreateUsingRabbitMq(sbc =>
    {
        var Host = sbc.Host(new Uri("rabbitmq://localhost"), h =>
        {
            h.Username("guest");
            h.Password("guest");
        });

        sbc.ReceiveEndpoint(Host, Configuration["QueueName"], e =>
        {
            e.LoadFrom(serviceProvider);
        });
    });

    // start/stop the bus with the web application
    applicationLifetime.ApplicationStarted.Register(bus.Start);
    applicationLifetime.ApplicationStopped.Register(bus.Stop);
}

Ein letzter Haftungsausschluss: Ich habe MassTransit nicht persönlich verwendet, daher weiß ich nicht wirklich, ob dies für die Bibliothek wirklich sinnvoll ist.

13
poke

Ich hatte auch das gleiche Problem und die Antwort von Poke funktionierte nicht für mich, da ich DI für IBus, IPublishEndpoint und ISendEndpointProvider verwenden musste. Ich habe die Lösung tatsächlich in einer gestrichenen Antwort gefunden, bei der genau zu dieser Frage eine Abstimmung stattgefunden hat. Schade wirklich, da hat es mir geholfen.

Ich habe dieses Beispiel gefunden hier

services.AddSingleton(provider => Bus.Factory.CreateUsingRabbitMq(cfg =>
{
   var Host = cfg.Host("localhost", "/", h => { });

   cfg.ReceiveEndpoint(Host, "web-service-endpoint", e =>
   {
      e.Consumer<DoSomethingConsumer>(provider);
   });
}));
1
ThePower