使用SimpleInjector获取HubContext

时间:2017-01-13 00:33:19

标签: c# signalr signalr-hub simple-injector

This guide似乎不适用于SimpleInjector。

我的OWIN初创公司看起来像这样:

container = new Container();
container.Options.DefaultScopedLifestyle = new ExecutionContextScopeLifestyle();

container.RegisterSingleton(() => new SimpleInjectorSignalRDependencyResolver(_container));
container.RegisterSingleton(() =>
    new HubConfiguration()
    {
        EnableDetailedErrors = true,
        Resolver = _container.GetInstance<SimpleInjectorSignalRDependencyResolver>()
    });

container.RegisterSingleton<IHubActivator, SimpleInjectorHubActivator>();
container.RegisterSingleton<IStockTicker,StockTicker>();
container.RegisterSingleton<HubContextAdapter<StockTickerHub, IStockTickerHubClient>>();
container.RegisterSingleton(() => GlobalHost.ConnectionManager);
container.Verify();

GlobalHost.DependencyResolver = container.GetInstance<SimpleInjectorSignalRDependencyResolver>();

app.Use(async (context, next) =>
{
    using (container.BeginExecutionContextScope())
    {
        await next();
    }
});

app.MapSignalR(container.GetInstance<HubConfiguration>());

HubContextAdapter看起来像这样:

public class HubContextAdapter<THub, TClient>
    where THub : Hub
    where TClient : class
{
    private readonly IConnectionManager _manager;

    public HubContextAdapter(IConnectionManager manager)
    {
        _manager = manager;
    }

    public IHubContext<TClient> GetHubContext()
    {
        return _manager.GetHubContext<THub, TClient>();
    }
}

SimpleInjectorSignalRDependencyResolver看起来像:

public class SimpleInjectorSignalRDependencyResolver : DefaultDependencyResolver
{
    public SimpleInjectorSignalRDependencyResolver(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public override object GetService(Type serviceType)
    {
        return _serviceProvider.GetService(serviceType) ?? base.GetService(serviceType);
    }

    public override IEnumerable<object> GetServices(Type serviceType)
    {
        var @this = (IEnumerable<object>)_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;
}

StockTicker看起来像:

public class StockTicker : IStockTicker
{
    private readonly HubContextAdapter<StockTickerHub, IStockTickerHubClient> _context;

    public StockTicker(HubContextAdapter<StockTickerHub, IStockTickerHubClient> context)
    {
        _context = context;
    }
}

StockTicker勾选并调用所有客户端来更新客户端方法时,不会调用并且没有网络流量。

1 个答案:

答案 0 :(得分:0)

SimpleInjector想要在验证后或第一次GetInstance调用后实例化单例。对于SignalR和StockTicker来说,这还为时过早,GlobalHost.ConnectionManager之前需要SimpleInjectorSignalRDependencyResolver的实例才是解析器。

我选择将IConnectionManager的依赖关系更改为Lazy<IConnectionManager>,将IStockTicker的依赖关系更改为Lazy<IStockTicker>,以便注册变为如下所示:

container = new Container();
container.Options.DefaultScopedLifestyle = new ExecutionContextScopeLifestyle();

container.RegisterSingleton(() => new SimpleInjectorSignalRDependencyResolver(_container));
container.RegisterSingleton(() =>
    new HubConfiguration()
    {
        EnableDetailedErrors = true,
        Resolver = _container.GetInstance<SimpleInjectorSignalRDependencyResolver>()
    });

container.RegisterSingleton<IHubActivator, SimpleInjectorHubActivator>();
container.RegisterSingleton<IStockTicker,StockTicker>();
container.RegisterSingleton<Lazy<IStockTicker>>(() => new Lazy<IStockTicker>(() => container.GetInstace<IStockTicker>()) );
container.RegisterSingleton<HubContextAdapter<StockTickerHub, IStockTickerHubClient>>();
container.RegisterSingleton(() => new Lazy<IConnectionManager>(() => GlobalHost.ConnectionManager));
container.Verify();