简体   繁体   中英

Get the HubContext using SimpleInjector

This guide does not appear to work for SimpleInjector.

My OWIN startup looks like this:

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>());

And The HubContextAdapter looks like this:

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>();
    }
}

And SimpleInjectorSignalRDependencyResolver looks like:

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;
}

And StockTicker looks like:

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

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

When the StockTicker ticks and calls all clients to update the client method is not invoked and there is no network traffic.

SimpleInjector wants to instantiate the singletons after verification or after the first GetInstance call. This is too early for SignalR and the StockTicker and it will take an instance of GlobalHost.ConnectionManager before SimpleInjectorSignalRDependencyResolver is the resolver.

I chose to change the dependency on IConnectionManager to be Lazy<IConnectionManager> and the dependency on IStockTicker to be Lazy<IStockTicker> so that registration became like the following:

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();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM