我有一个传奇,我正在尝试与需要改装客户端的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“
答案 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客户端之类的东西。如果传奇需要获取一些数据来决定邮件路由,则应该使用邮件来获取数据。