gpt4 book ai didi

c# - 使用 Autofac 将对象注入(inject) MassTransit Saga

转载 作者:行者123 更新时间:2023-11-30 16:59:57 24 4
gpt4 key购买 nike

我试图让 autofac 在创建时将工厂注入(inject)到 saga 中,但我无法让它工作。我在将工厂注入(inject)消费者时没有遇到任何问题,所以我知道它已正确注册,所以我假设我没有正确注册 sagas 并且 autofac 没有构建它们。

这是我的注册码:

var mapTypes = assembly.GetTypes()
.Where(type => type.Implements(typeof(SagaClassMapping<>)));

builder.Register(context => GetSessionFactory(mapTypes)).AsSelf().SingleInstance();

// register all sagas and consumers
builder.RegisterAssemblyTypes(assembly)
.Where(type => type.IsAssignableTo<ISaga>() || type.IsAssignableTo<IConsumer>())
.AsSelf();

builder
.RegisterGeneric(typeof(NHibernateSagaRepository<>))
.As(typeof(ISagaRepository<>))
.SingleInstance();

builder
.Register(context => ServiceBusFactory.New(sbc =>
{
sbc.UseLog4Net();
var queueUri = new Uri(ConfigurationManager.AppSettings["ReceiveQueue"]);
var scope = context.Resolve<ILifetimeScope>();
sbc.UseRabbitMq(transportConfig =>
transportConfig.ConfigureHost(queueUri, hostConfig =>
{
hostConfig.SetUsername(ConfigurationManager.AppSettings["busUser"]);
hostConfig.SetPassword(ConfigurationManager.AppSettings["busPassword"]);
}));
sbc.ReceiveFrom(queueUri);
sbc.Subscribe(cfg => cfg.LoadFrom(scope));
}))
.SingleInstance();

传奇本身很标准

public class MySaga : SagaStateMachine<MySaga>, ISaga
{
public Guid CorrelationId { get; private set; }
public Func<MyObject> ObjectBuilder { get; set; }
public MySaga() { }

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

Static MySaga()
{
Define(() =>
{ .... }
}

我试过添加 Func<MyObject>到构造函数,但它没有被击中,它确实在消费者中工作所以我知道 Autofac 可以构建一个 Func<MyObject> .我也尝试过使用属性注入(inject),但没有成功:

builder.RegisterAssemblyTypes(assembly)
.Where(type => type.IsAssignableTo<ISaga>() || type.IsAssignableTo<IConsumer>())
.PropertiesAutowired()
.AsSelf();

builder.RegisterType<MySaga>()
.OnActivated(arg => arg.Instance.MyBuilder =
arg.Context.Resolve<Func<MyObject>>())
.AsSelf();

对于我做错的任何帮助,我们将不胜感激。


我在 masstransit-discuss group 上收到了 Chris Patterson 的回复这指出我可能做错了。

Automatonymous is a better choice if you have dependencies, since the state machine and the state itself are separate classes.

Injecting dependencies into a class hydrated via NHibernate is never going to end well. There are a couple of helper classes that can be used to perform property-injection into the saga after it is loaded from NHibernate, the decorating saga repository I think has been posted here.

Here is the example of the injecting repository for Magnum:https://github.com/MassTransit/MassTransit/blob/master/src/MassTransit.Tests/Saga/Injecting_Specs.cs

鉴于 NHibernate 正在为对象补水,我应该在那里寻找钩子(Hook)。我有解决当前问题的方法,但如果/当我找到答案时,我会在此处发布答案。

最佳答案

老问题,但我们花了一段时间才找到一种合适的方法来连接 sagas 和 autofac,然后在其上添加 nhibernate。

首先创建一个布线类(属性注入(inject))

public class MySagaRepository<TSaga> : ISagaRepository<TSaga> where TSaga : class, ISaga
{
private ISagaRepository<TSaga> _inner;
private readonly IComponentContext _context;

public MySagaRepository(ISagaRepository<TSaga> inner, IComponentContext context)
{
_inner = inner;
_context = context;
}

public IEnumerable<Action<IConsumeContext<TMessage>>> GetSaga<TMessage>(IConsumeContext<TMessage> context, Guid sagaId, InstanceHandlerSelector<TSaga, TMessage> selector, ISagaPolicy<TSaga, TMessage> policy) where TMessage : class
{
return _inner.GetSaga(context, sagaId, (saga, message) =>
{
_context.InjectProperties(saga);
return selector(saga, message);
}, policy);
}

public IEnumerable<Guid> Find(ISagaFilter<TSaga> filter)
{
return _inner.Find(filter);
}

public IEnumerable<TSaga> Where(ISagaFilter<TSaga> filter)
{
return _inner.Where(filter).Select(x =>
{
_context.InjectProperties<TSaga>(x);
return x;
});
}

public IEnumerable<TResult> Where<TResult>(ISagaFilter<TSaga> filter, Func<TSaga, TResult> transformer)
{
return _inner.Where(filter, x =>
{
_context.InjectProperties(x);
return transformer(x);
});
}

public IEnumerable<TResult> Select<TResult>(Func<TSaga, TResult> transformer)
{
return _inner.Select(x =>
{
_context.InjectProperties(x);
return transformer(x);
});
}
}

然后接线

builder.RegisterGeneric(typeof(NHibernateSagaRepository<>)).Named("innerRepo", typeof(ISagaRepository<>));
builder.RegisterGenericDecorator(typeof(MySagaRepository<>), typeof(ISagaRepository<>), fromKey: "innerRepo");

为了坚持,这只是一个问题

public class SagaPersistenceHandler
{
public static ISessionFactory CreateSessionFactory()
{
var provider = new SqlServerSessionFactoryProvider(ConfigurationManager.ConnectionStrings["myConnectionString"].ConnectionString, new[]
{
typeof (MySagaMap)
});

return provider.GetSessionFactory();
}
}

现在连线

builder.Register(c => SagaPersistenceHandler.CreateSessionFactory()).As<ISessionFactory>();

和 saga 映射到 saga(不包括在内)

public MySagaMap()
{
SchemaAction(NHibernate.Mapping.ByCode.SchemaAction.None);
Table("dbo.[tTable]");
Property(x => x.Id);
Property(x => x.CloseDate);
}
}

剩下的就是注册你的 saga

builder.RegisterType<MySaga>().AsSelf(); 

工作得很好(归功于@erikkallen)

关于c# - 使用 Autofac 将对象注入(inject) MassTransit Saga,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22978339/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com