gpt4 book ai didi

inversion-of-control - SignalR 和 CaSTLe Windsor 的正确 Hub 依赖生命周期管理

转载 作者:行者123 更新时间:2023-12-03 07:52:11 24 4
gpt4 key购买 nike

我有一些 SignalR 集线器,它们可能需要访问一些 transient 和单例依赖项。 Hook 集线器的创建很容易并且工作得很好,但是 SignalR 会在创建的集线器上执行自己的 Dispose() 调用,而不是通知依赖项解析器并让它参与处理。

如果依赖项是注册的单例,这不是什么大问题,但是如果它们被注册为 transient ,那么它们将永远不会被处理(如果需要的话)并且 Windsor 将保持它们活着直到收集 Windsor 容器(当无论如何,Web 服务器正在关闭)。

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

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

b) SignalR 中的其他一些类,在管道的其他地方,可以被覆盖或轻松替换,以便我们可以子类化 HubDispatcher 并确保使用子类。据我所知,这必须是 Owin 中间件类 HubDispatcherMiddleware。有没有办法强制 Owin 不注册这个类,而是注册我自己的这个版本(反过来使用我自己的 HubDispatcher)?

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

d) 刻意避免使用 transient 生活方式依赖项,而是传入类型化工厂,以便我们可以通过 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() 可能会增加一些复杂性(我不太确定有多少,我对CaSTLe 的拦截器以及是否可以解决对 IDisposable 的丢失转换)。

我很感激我为相当狭窄的受众编写了这个问题 - 那些使用过 Windsor 和 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);
    }
    }

    关于inversion-of-control - SignalR 和 CaSTLe Windsor 的正确 Hub 依赖生命周期管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21967542/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com