使用Autofac将对象注入MassTransit Saga

时间:2014-04-10 03:53:09

标签: c# nhibernate autofac masstransit

我正试图让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 group的答复,指出我可能做错了。

  

如果你有依赖关系,Automatonymous是一个更好的选择,因为状态机和状态本身是单独的类。

     

通过NHibernate注入依赖于水合的类永远不会结束。从NHibernate加载后,有几个辅助类可用于对saga执行属性注入,我认为装饰传奇存储库已在此处发布。

     

以下是Magnum注入存储库的示例:   https://github.com/MassTransit/MassTransit/blob/master/src/MassTransit.Tests/Saga/Injecting_Specs.cs

鉴于它的NHibernate正在保护物体,我应该在那里寻找钩子。我的当前问题有一个解决方法,但如果/当我找到答案时,我会在这里发布答案。

2 个答案:

答案 0 :(得分:1)

老问题但我们需要一段时间才能找到一种合适的方法来连接传单和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>();

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

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

剩下的就是注册你的传奇

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

运作良好(积分归@erikkallen)

答案 1 :(得分:1)

我为Autofac制作了一个适配器来注册和配置MT状态机传奇。

回购是here

可在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实施。

相关问题