使用依赖项注入设置传奇的Masstransit错误

时间:2019-01-23 03:19:51

标签: dependency-injection .net-core masstransit

我有一个传奇,我正在尝试与需要改装客户端的masstransit一起运行,并且我想将客户端依赖性注入到传奇中。

我将MassTransit 5.2.3与MassTransit.Extensions.DependencyInjection 5.2.3结合使用,以进行以下设置:

...
var serviceCollection = new ServiceCollection();
serviceCollection.AddRefitClient<IClient>(...).ConfigureHttpClient(...);
serviceCollection.AddMassTransit(c =>
{
    c.AddSaga<MySaga>();
});    
serviceCollection.AddScoped<MySaga>();
serviceCollection.AddSingleton<ISagaRepository<MySaga>, MessageSessionSagaRepository<MySaga>>(x => new MessageSessionSagaRepository<MySaga>());

var serviceProvider = serviceCollection.BuildServiceProvider();
var bus = Bus.Factory.CreateUsingAzureServiceBus(cfg =>
{
    var host = ...;
    ...
    cfg.ReceiveEndpoint(host, "MyQueue", e =>
    {   
        ... 
        e.Saga<MySaga>(serviceProvider);
    });
});

bus.Start();
...

传奇的代码是:

class MySaga :
    ISaga,
    InitiatedBy<IStep1>,
    Orchestrates<IStep2>
{
    private readonly IClient _client;

    public Guid CorrelationId { get; set; }

    public MySaga(IClient client)
    {
        _client = client;
    }

    public async Task Consume(ConsumeContext<IStep1> context) {...}
    public async Task Consume(ConsumeContext<IStep2> context) {...}
}

这将导致“无法为MyNamespace.MySaga创建saga连接器”异常,内部异常是“ ConfigurationException:saga MyNamespace.MySaga必须具有默认构造函数和可写的CorrelationId属性,或者具有单个Guid参数的构造函数分配CorrelationId“

1 个答案:

答案 0 :(得分:0)

MassTransit对sagas的关注点已移至状态机sagas,因此总体上首选Automatonymous sagas。对于“经典” sagas,错误消息中已为您提供了要求。您可以使用Injection_Specs.cs

中的代码
var refitClient = ...;

var serviceCollection = new ServiceCollection();
serviceCollection.AddMassTransit(c =>
{
    c.AddSaga<MySaga>();
});    
serviceCollection.AddScoped<MySaga>();
serviceCollection.AddSingleton<ISagaRepository<MySaga>, MessageSessionSagaRepository<MySaga>>(x => new MessageSessionSagaRepository<MySaga>());

var serviceProvider = serviceCollection.BuildServiceProvider();
var bus = Bus.Factory.CreateUsingAzureServiceBus(cfg =>
{
    var host = ...;
    ...
    cfg.ReceiveEndpoint(host, "MyQueue", e =>
    {   
        ... 
        e.Saga<MySaga>(serviceProvider, 
            x => x.UseExecute(ctx => ctx.Saga.Client = refitClient));
    });
});

bus.Start();

当然,您需要在saga类中拥有Client公共属性,并且不会使用构造函数注入。您还需要错误消息告诉您拥有的这两个构造函数:

class MySaga :
    ISaga,
    InitiatedBy<IStep1>,
    Orchestrates<IStep2>
{
    public IClient Client { get; set; }

    public Guid CorrelationId { get; set; }

    public MySaga()
    {
    }

    public MySaga(Guid correlationId)
    {
        CorrelationId = correlationId;
    }

    public async Task Consume(ConsumeContext<IStep1> context) {...}
    public async Task Consume(ConsumeContext<IStep2> context) {...}
}

设计考虑因素

我必须添加的一件事是MassTransit中的Saga接近于Process Manager模式。这意味着sagas除了业务流程逻辑外不应具有任何逻辑,并且除了处理消息外不应执行其他任何操作。因此,我不建议在sagas中使用诸如REST API客户端之类的东西。如果传奇需要获取一些数据来决定邮件路由,则应该使用邮件来获取数据。

相关问题