Simple Injector per-web-api-request dependency in SignalR hub

后端 未结 2 639
野趣味
野趣味 2021-01-02 18:13

According to this post, it should be possible to inject per-web-request dependencies into SignalR hubs (although with some limitations like problem with OnDisconnected() met

2条回答
  •  误落风尘
    2021-01-02 18:22

    Recently I faced the same problem and found the following working quite well, hope this will help someone:

    public class SignalRDependencyResolver : DefaultDependencyResolver
    {
        public SignalRDependencyResolver(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }
    
        public override object GetService(Type serviceType)
        {
            return _serviceProvider.GetService(serviceType) ?? base.GetService(serviceType);
        }
    
        public override IEnumerable GetServices(Type serviceType)
        {
            var @this = (IEnumerable) _serviceProvider.GetService(typeof (IEnumerable<>).MakeGenericType(serviceType));
    
            var @base = base.GetServices(serviceType);
    
            return @this == null ? @base : @base == null ? @this : @this.Concat(@base);
        }
    
        private readonly IServiceProvider _serviceProvider;
    }
    
    public class SignalRHubDispatcher : HubDispatcher
    {
        public SignalRHubDispatcher(Container container, HubConfiguration configuration) : base(configuration)
        {
            _container = container;
        }
    
        protected override Task OnConnected(IRequest request, string connectionId)
        {
            return Invoke(() => base.OnConnected(request, connectionId));
        }
    
        protected override Task OnReceived(IRequest request, string connectionId, string data)
        {
            return Invoke(() => base.OnReceived(request, connectionId, data));
        }
    
        protected override Task OnDisconnected(IRequest request, string connectionId, bool stopCalled)
        {
            return Invoke(() => base.OnDisconnected(request, connectionId, stopCalled));
        }
    
        protected override Task OnReconnected(IRequest request, string connectionId)
        {
            return Invoke(() => base.OnReconnected(request, connectionId));
        }
    
        private async Task Invoke(Func method)
        {
            using (_container.BeginExecutionContextScope())
                await method();
        }
    
        private readonly Container _container;
    }
    
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            var container = new Container();
    
            container.Options.DefaultScopedLifestyle = new ExecutionContextScopeLifestyle();
    
            container.Register(Lifestyle.Scoped);
            container.Register(Lifestyle.Scoped);
    
            // if you want to use the same container in WebApi don't forget to add
            app.Use(async (context, next) => {
                using (container.BeginExecutionContextScope())
                    await next();
            });
    
            // ... configure web api 
    
            var config = new HubConfiguration
            {
                Resolver = new SignalRDependencyResolver(container)
            }
    
            // ... configure the rest of SignalR
    
            // pass SignalRHubDispatcher
            app.MapSignalR("/signalr", config);
        }
    }
    
        

    提交回复
    热议问题