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