适用于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。
我的要求:
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