适用于SignalR和Castle Windsor的Hub依赖性生命周期管理

我有一些SignalR集线器可能需要访问一些瞬态和单例依赖关系。 钩住Hub的创建非常简单,而且工作得很好,但SignalR在创建的Hub上执行自己的Dispose()调用,而不是通知依赖关系解析器并让它参与处理。

如果依赖关系是单身人士注册,这并不是什么大问题,但是如果他们被注册为瞬态,那么他们将永远不会被处置(如果需要的话),并且Windsor会保留他们直到收集Windsor容器(当无论如何,Web服务器正在关闭)。

我看到了几种可能的处理方法...

a)这里有人指出了一种方法来划分SignalR的HubDispatcher类的子类,以便它可以做适当的处理。 它不是SignalR的标准DependencyResolver的一部分,所以这可能很难/不可能

b)SignalR中的其他一些类,在管道中的其他地方,可以重写或轻易替换,以便我们可以继承HubDispatcher并确保使用子类。 从我可以告诉的这将是欧文中间件类HubDispatcherMiddleware。 有没有办法强制Owin不注册这个类,而是注册我自己的这个版本(反过来使用我自己的HubDispatcher)?

c)有一些方法可以拦截由我的Hub类上的SignalR进行的Dispose()调用,以便可以将呼叫返回到Windsor以确保任何依赖关系都可以正确处理并从容器中释放

d)尽量避免使用短暂的生活方式依赖关系,而是传递类型化的工厂,以便我们可以通过Hub内的类型化工厂解决并释放每个依赖关系

目前(d)是我唯一知道该怎么做的人。 (a)或(b)会很好。 (c)主要是由这篇文章http://kozmic.net/2010/01/27/transparently-releasing-components-in-windsor/覆盖,但是,拦截器要求通过IDisposable调用Dispose()。 SignalR的HubDispather类实现集线器处置

private static void DisposeHubs(IEnumerable<IHub> hubs)
{
    foreach (var hub in hubs)
    {
        hub.Dispose();
    }
}

没有在IDisposable那里投射......另外,Hub类的Dispose()是虚拟的,博客文章暗示虚拟Dispose()可能会增加一些复杂性(我不太确定有多少,但我不太了解无论如何,城堡的拦截器以及是否缺少投射到IDisposable都可以解决)。

我很欣赏我为一个相当狭窄的受众撰写了这个问题 - 那些使用Windsor AND SignalR并且关心的不仅仅是解决依赖问题。 我发现的每个示例(包括StackOverflow上的示例)似乎都忽略了依赖关系的发布。

谢谢!


我遇到了一些类似的问题,但用Unity代替Castle Windsor。

我的要求:

  • 我想避免在容器上进行单身人士注册。
  • 所有对象都在Hub中解析并且应该放置在Hub销毁。
  • 注册在Web Api和SignalR中重复使用。
  • 对象生命周期由HierarchicalLifetimeManager管理 - 子容器解析和管理单独的对象实例。 像这样注册:
  • container.RegisterType<IMessageService, MessageService>(new HierarchicalLifetimeManager());
    

    这是我的解决方案:

    [HubName("exampleHub")]
    public class ExampleHub : Hub
    {
        IUnityContainer _container;
    
        public CarrierApiHub(IUnityContainer container) // container itself injected in hub
        {
            _container = container.CreateChildContainer(); // child container derived from the main container.
        }
    
        public async Task<int> UnreadMessagesCount()
        {
            // Here i'm resolving instance of IMessageService which depends on
            // other registrations specified on the container. Full object graph
            // is constructed and destroyed on hub disposal.
            var messageSvc = _container.Resolve<IMessageService>();
            return await messageSvc.CountUnreadOf(UserId);
        }
    
        protected override void Dispose(bool disposing)
        {
            _container.Dispose(); // child container destroyed. all resolved objects disposed.
            base.Dispose(disposing);
        }
    
        private int UserId
        {
            get
            {
                // only an example
                var claim = ((ClaimsPrincipal)Context.User).GetClaim("user_id");
                return int.Parse(claim.Value);
            }
        }
    }
    

    SignalR和依赖关系解析器配置:

    public static class ConfigureSignalR
    {
        public static void Initialize(UnityContainer unityContainer, IAppBuilder app)
        {
            app.Map("/signalr", map =>
            {
                var resolver = new AppSignalRDependencyResolver(unityContainer);
    
                map.UseCors(CorsOptions.AllowAll);
    
                var hubConfiguration = new HubConfiguration
                {
                    EnableJavaScriptProxies = false,
                    EnableJSONP = true, // Required for IE 9 (supports only polling)
                    Resolver = resolver
                };
    
                map.RunSignalR(hubConfiguration);
            });
        }
    }
    

    依赖解析器的实现:

    public class AppSignalRDependencyResolver : DefaultDependencyResolver
    {
        protected IUnityContainer _container;
    
        public AppSignalRDependencyResolver(IUnityContainer container)
        {
            if (container == null)
            {
                throw new ArgumentNullException("container");
            }
            this._container = container.CreateChildContainer();
        }
    
        public override object GetService(Type serviceType)
        {
            try
            {
                return _container.Resolve(serviceType);
            }
            catch (ResolutionFailedException)
            {
                return base.GetService(serviceType);
            }
        }
    
        public override IEnumerable<object> GetServices(Type serviceType)
        {
            try
            {
                return _container.ResolveAll(serviceType).Concat(base.GetServices(serviceType));
            }
            catch (ResolutionFailedException)
            {
                return base.GetServices(serviceType);
            }
        }
    
        protected override void Dispose(bool disposing)
        {
            _container.Dispose();
            base.Dispose(disposing);
        }
    }
    
    链接地址: http://www.djcxy.com/p/96175.html

    上一篇: Proper Hub dependency lifetime management for SignalR and Castle Windsor

    下一篇: Sharing a SignalR hub between a WebApi and MVC project