Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将依赖注入到NServiceBus管道行为中?_Nservicebus - Fatal编程技术网

如何将依赖注入到NServiceBus管道行为中?

如何将依赖注入到NServiceBus管道行为中?,nservicebus,Nservicebus,我一直在关注NServiceBus示例,特别是关于如何使用与Sql持久性集成的实体框架(核心)DbContext,以便可以将DbContext状态更改与发件箱消息一起保存。以下是示例: 我稍微修改了工作单元代码,以支持创建aspnet核心DI作用域DbContext。有关守则如下: public class UnitOfWork<TDbContext> where TDbContext : DbContext { private Fun

我一直在关注NServiceBus示例,特别是关于如何使用与Sql持久性集成的实体框架(核心)DbContext,以便可以将DbContext状态更改与发件箱消息一起保存。以下是示例:

我稍微修改了工作单元代码,以支持创建aspnet核心DI作用域DbContext。有关守则如下:

    public class UnitOfWork<TDbContext>
        where TDbContext : DbContext
    {
        private Func<SynchronizedStorageSession, IServiceProvider, TDbContext> _contextFactory;
        private TDbContext _context;
        private IServiceProvider _serviceProvider;

        public UnitOfWork(Func<SynchronizedStorageSession, IServiceProvider, TDbContext> contextFactory, IServiceProvider serviceProvider)
        {
            _contextFactory = contextFactory;
            _serviceProvider = serviceProvider;
        }

        public TDbContext GetDataContext(SynchronizedStorageSession storageSession)
        {
            if (_context == null)
            {
                _context = _contextFactory(storageSession, _serviceProvider);
            }
            return _context;
        }
    }

    public class UnitOfWorkSetupBehavior<TDbContext> : Behavior<IIncomingLogicalMessageContext>
        where TDbContext : DbContext
    {
        private readonly Func<SynchronizedStorageSession, IServiceProvider, TDbContext> _contextFactory;
        private readonly IServiceScopeFactory _serviceScopeFactory;

        public UnitOfWorkSetupBehavior(Func<SynchronizedStorageSession, IServiceProvider, TDbContext> contextFactory, IServiceScopeFactory serviceScopeFactory)
        {
            _contextFactory = contextFactory;
            _serviceScopeFactory = serviceScopeFactory;
        }

        public override async Task Invoke(IIncomingLogicalMessageContext context, Func<Task> next)
        {
            using (var scope = _serviceScopeFactory.CreateScope())
            {
                var uow = new UnitOfWork<TDbContext>(_contextFactory, scope.ServiceProvider);
                context.Extensions.Set(uow);

                await next().ConfigureAwait(false);

                context.Extensions.Remove<UnitOfWork<TDbContext>>();
            }
        }
    }

    public static class EndpointConfigurationExtensions
    {
        public static void RegisterUnitOfWork<TDbContext>(this EndpointConfiguration endpointConfiguration, IServiceScopeFactory serviceScopeFactory)
            where TDbContext : DbContext
        {
            var pipeline = endpointConfiguration.Pipeline;
            pipeline.Register(new UnitOfWorkSetupBehavior<TDbContext>((storageSession, serviceProvider) =>
            {
                var dbConnection = storageSession.SqlPersistenceSession().Connection;
                var dbContextFactory = serviceProvider.GetService<IDbContextConnectionFactory<TDbContext>>();
                var dbContext = dbContextFactory.GetDbContext(dbConnection);

                //Use the same underlying ADO.NET transaction
                dbContext.Database.UseTransaction(storageSession.SqlPersistenceSession().Transaction);

                //Call SaveChanges before completing storage session
                storageSession.SqlPersistenceSession().OnSaveChanges(x => dbContext.SaveChangesAsync());

                return dbContext;
            }, serviceScopeFactory), "Sets up unit of work for the message");
        }
    }

    public static class UnitOfWorkContextExtensions
    {
        public static TDbContext DataContext<TDbContext>(this IMessageHandlerContext context)
            where TDbContext : DbContext
        {
            var uow = context.Extensions.Get<UnitOfWork<TDbContext>>();
            return uow.GetDataContext(context.SynchronizedStorageSession);
        }
    }

公共类UnitOfWork
其中TDbContext:DbContext
{
私人Func_contextFactory;
私有TDbContext_上下文;
私人IServiceProvider_服务提供商;
公共工作单元(Func contextFactory、IServiceProvider服务提供商)
{
_contextFactory=contextFactory;
_服务提供者=服务提供者;
}
公共TDbContext GetDataContext(SynchronizedStorageSession-storageSession)
{
if(_context==null)
{
_上下文=_contextFactory(storageSession,_serviceProvider);
}
返回上下文;
}
}
公共类UnitOfWorkSetupBehavior:行为
其中TDbContext:DbContext
{
私有只读Func_contextFactory;
专用readonly IServiceScopeFactory\u serviceScopeFactory;
公共UnitOfWorkSetupBehavior(Func上下文工厂、IServiceScopeFactory服务范围工厂)
{
_contextFactory=contextFactory;
_serviceScopeFactory=serviceScopeFactory;
}
公共重写异步任务调用(IIncomingLogicalMessageContext上下文,Func next)
{
使用(var scope=\u serviceScopeFactory.CreateScope())
{
var uow=新的工作单元(_contextFactory,scope.ServiceProvider);
context.Extensions.Set(uow);
wait next().configurewait(false);
Extensions.Remove();
}
}
}
公共静态类EndpointConfigurationExtensions
{
公共静态无效注册表监视工作(此EndpointConfiguration EndpointConfiguration,IServiceScopeFactory serviceScopeFactory)
其中TDbContext:DbContext
{
var pipeline=endpointConfiguration.pipeline;
pipeline.Register(新UnitOfWorkSetupBehavior)((storageSession,serviceProvider)=>
{
var dbConnection=storageSession.SqlPersistenceSession().Connection;
var dbContextFactory=serviceProvider.GetService();
var dbContext=dbContextFactory.GetDbContext(dbConnection);
//使用相同的底层ADO.NET事务
dbContext.Database.UseTransaction(storageSession.SqlPersistenceSession().Transaction);
//在完成存储会话之前调用SaveChanges
storageSession.SqlPersistenceSession().OnSaveChanges(x=>dbContext.SaveChangesSync());
返回dbContext;
},serviceScopeFactory),“设置消息的工作单元”);
}
}
公共静态类UnitOfWorkContextensions
{
公共静态TDbContext数据上下文(此IMessageHandlerContext上下文)
其中TDbContext:DbContext
{
var uow=context.Extensions.Get();
返回uow.GetDataContext(context.SynchronizedStorageSession);
}
}
为此,行为需要注入IServiceScopeFactory

现在,我能找到的所有行为注册示例都只显示手动实例化并传递到endpointconfiguration管道的类型

有没有一种方法可以通过行为的Invoke方法访问IServiceScopeFactory(可能通过某种扩展通过上下文),或者可以注册行为本身,以便我可以使用DI容器创建的服务来构建它


仅供参考,我看了一看Q&a,它让我想到了注入IserviceScope工厂。不幸的是,答案没有显示如何实际获取接口实例。

您可以使用
context.builder.Build()Invoke
方法中的code>解析任何对象,如
IServiceScopeFactory

确保在DI容器中注册了IServiceScopeFactory。例如,在端点初始化期间:

endpointConfiguration.RegisterComponents(registration: x =>
    {
        x.ConfigureComponent<IServiceScopeFactory>(yourServiceScopeFactory);
    });
endpointConfiguration.RegisterComponents(注册:x=>
{
x、 配置组件(您的ServiceScopeFactory);
});
也可以通过创建特征来完成此操作


Ramon,我不确定第一行说我应该使用什么,但多租户链接帮助了我。我假设它的意思是写“context.builder.Build()”,因为这就是我使用的有效方法?如果你把这条线修好,我会标上正确的。只是补充一下,我不需要组件注册,因为我使用MS DI托管在dotnet core通用主机中。不过我会在你的回答中留下这些信息。