[英]Injecting objects into a MassTransit Saga using Autofac
我正试图让autofac将一个工厂注入创造的传奇,我无法让它工作。 我没有把工厂注入消费者的问题所以我知道它已正确注册,所以我假设我没有正确注册传真,而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>
。 我也尝试过使用属性注入而没有运气:
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();
对我所做错的任何帮助都将不胜感激。
我得到了Chris Patterson对masstransit-discuss小组的回复,指出我可能做错了。
如果你有依赖关系,Automatonymous是一个更好的选择,因为状态机和状态本身是单独的类。
通过NHibernate将依赖关系注入到水合中的类永远不会结束。 从NHibernate加载后,有几个辅助类可用于执行属性注入到saga中,我认为装饰传奇存储库已在此处发布。
以下是Magnum注入存储库的示例: https : //github.com/MassTransit/MassTransit/blob/master/src/MassTransit.Tests/Saga/Injecting_Specs.cs
鉴于它的NHibernate正在保护物体,我应该在那里寻找钩子。 我的当前问题有一个解决方法,但如果/当我找到一个,我会在这里发布一个答案。
旧的问题,但我们花了一段时间才找到一个合适的方法来连接传奇和autofac,然后添加nhibernate。
首先创建一个布线类(属性注入)
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>();
和传奇映射到传奇(不包括在内)
public MySagaMap()
{
SchemaAction(NHibernate.Mapping.ByCode.SchemaAction.None);
Table("dbo.[tTable]");
Property(x => x.Id);
Property(x => x.CloseDate);
}
}
剩下的就是注册你的传奇
builder.RegisterType<MySaga>().AsSelf();
工作得很好(学分归@erikkallen)
我为Autofac制作了一个适配器来注册和配置MT状态机传奇。
回购在这里 。
它可以在nuget.org上找到。
您可以通过以下方式注册您的消费者和州机器:
builder.RegisterSagaStateMachines(sagasAssembly); // register all state machines
builder.RegisterConsumers(consumersAssembly); // register consumers (standard MassTransit Autofac integration)
请注意, RegisterConsumers
是标准的MassTransit.Autofac
扩展。
在端点配置中,您需要调用以下配置:
x.ReceiveEndpoint(queueName, c =>
{
c.LoadConsumers(container);
c.LoadStateMachineSagas(container);
});
前提条件是您还必须注册ISagaRepository
实现。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.