问题
I am trying to get SignalR working with Autofac. I have a repo of a stripped back version of what I have done here:
https://github.com/justsayno/signalr-autofac
This is adapted from which works using GlobalHost
:
https://github.com/sstorie/experiments/tree/master/angular2-signalr
That works just fine using hte GlobalHost object. I have attempted to follow the documentation on Autofac's site about how to inject SignalR services but I cannot get it to work. This is my config file for registering my dependencies:
public static IContainer RegisterDependencies()
{
// Create your builder.
var builder = new ContainerBuilder();
//register controllers in DI
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// Register SignalR hubs
builder.RegisterHubs(Assembly.GetExecutingAssembly());
return builder.Build();
}
And I call this from startup.cs:
public class Startup
{
public static IContainer Container { get; set; }
public void Configuration(IAppBuilder app)
{
var config = GlobalConfiguration.Configuration;
// configure IoC container
Container = AutofacConfiguration.RegisterDependencies();
//set dependency resolver from WebAPI and MVC
config.DependencyResolver = new AutofacWebApiDependencyResolver(Container);
DependencyResolver.SetResolver(new Autofac.Integration.Mvc.AutofacDependencyResolver(Container));
//register Autofac Middleware
app.UseAutofacMiddleware(Container);
app.Map("/signalr", a =>
{
a.UseCors(CorsOptions.AllowAll);
var hubConfiguration = new HubConfiguration
{
Resolver = new Autofac.Integration.SignalR.AutofacDependencyResolver(Container)
};
a.RunSignalR(hubConfiguration);
});
// This server will be accessed by clients from other domains, so
// we open up CORS
//
app.UseCors(CorsOptions.AllowAll);
// Build up the WebAPI middleware
//
var httpConfig = new HttpConfiguration();
httpConfig.MapHttpAttributeRoutes();
app.UseWebApi(httpConfig);
}
}
And I have a controller that has this injected into its contstructor:
public TaskController(IHubContext hubContext)
{
// Commented out hard coded global host version
//
//_context = GlobalHost.ConnectionManager.GetHubContext<EventHub>();
// using DI
_context = hubContext;
}
This however gives me an error about the controller not having a default constructor (so I assume this is a problem with my IHubContext not being found).
Any help would be great. I have made a repo of what I am talking about that can be found here for a complete solution:
https://github.com/justsayno/signalr-autofac
回答1:
I've been able to do this, but it's not as clean as I would normally like. The primary issue here is that IHubContext does not reflect what specific type of hub it is...it's just a generic handle. So what I've done is to create a named registration within Autofac to register IHubContext using a specific SignalR hub:
builder.Register(ctx =>
ctx.Resolve<IDependencyResolver>()
.Resolve<IConnectionManager>()
.GetHubContext<EventHub>())
.Named<IHubContext>("EventHub");
Then I set up specific registrations for the objects I'll be injecting this hub into. This could be either an ApiController, or perhaps some other service that is then injected into controllers using the standard Autofac/WebApi integration. This "specific" registration is the piece I don't like, but I don't know of a cleaner way around it. Here's what that would look like:
builder.RegisterType<TaskController>()
.WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(IHubContext),
(pi, ctx) => ctx.ResolveNamed<IHubContext>("EventHub")
)
);
Now Autofac should recognize that you want to inject IHubContext into the TaskController
and provide the specific registration named EventHub when injecting it.
来源:https://stackoverflow.com/questions/37912330/autofac-injection-of-ihubcontext-signalr-mvc