使用Unity IoC注册和解决SignalR集线器

时间:2014-01-05 02:02:13

标签: dependency-injection unity-container signalr ioc-container signalr-hub

我想我错过了一些非常简单的事情,也许只需要一副新的眼睛。我有一个ASP.NET MVC应用程序。在那个应用程序中,我使用Unity来处理IoC来处理依赖注入。我的每个存储库都需要注入一个数据库工厂,每个数据库工厂都需要注入一个主体。到目前为止,我一直在使用PerRequestLifetimeManager来注册这些。

//Repositories

container.RegisterType<ChatMessageRepository>(new PerRequestLifetimeManager());
           container.RegisterType<SignalRConnectionRepository>(new PerRequestLifetimeManager());

//Context
container.RegisterType<IPrincipal, Principal>(new PerRequestLifetimeManager());
container.RegisterType<IDatabaseFactory, DatabaseFactory>(new PerRequestLifetimeManager());
container.RegisterType<UnitOfWork>(new PerRequestLifetimeManager());

逻辑上,我试图以同样的方式注册我的Hub。

container.RegisterType<ChatHub>(new PerRequestLifetimeManager()); 

然而,每当我运行我的应用程序并离开我的聊天页面时,我得到“依赖失败的解决方案”异常,而InnerException告诉我“由于对象的当前状态,操作无效”。我也尝试使用默认(Transient),PerResolve和ContainerControlled生命周期Unity管理员注册这些人,似乎无法解决我的问题。

有人可以向我提供一些演示代码,说明如何在ASP.NET MVC应用程序中使用Unity来处理信号中心的依赖注入吗?

Unity将把参数注入我的SignalR Hub

public class ChatHub : Hub
{
    private readonly ChatMessageRepository _chatMessageRepository;
    private readonly SignalRConnectionRepository _signalRConnectionRepository;
    private readonly UnitOfWork _unitOfWork;

    public ChatHub(ChatMessageRepository chatMessageRepository,
        SignalRConnectionRepository signalRConnectionRepository,
        UnitOfWork unitOfWork)
    {
        _chatMessageRepository = chatMessageRepository;
        _signalRConnectionRepository = signalRConnectionRepository;
        _unitOfWork = unitOfWork;
    } ... }

谢谢!

3 个答案:

答案 0 :(得分:16)

分3步完成

首先。创建UnityHubActivator类

public class UnityHubActivator : IHubActivator
{
    private readonly IUnityContainer _container;

    public UnityHubActivator(IUnityContainer container)
    {
        _container = container;
    }

    public IHub Create(HubDescriptor descriptor)
    {
        return (IHub)_container.Resolve(descriptor.HubType);
    }
}

二。在运行Startup class

之前创建Unity容器并注册依赖项解析程序
unityContainer = new UnityContainer();
var unityHubActivator = new UnityHubActivator(_unityContainer);
GlobalHost.DependencyResolver.Register(typeof(IHubActivator), () => unityHubActivator);
//register some types in container
WebApp.Start<Startup>(startOptions);

第三。在您的集线器中使用它

public class MyHub : Hub
{
    public MyHub(Logger logger)
    {
        logger.Info("hub constructor");
    }
}

请注意。我在Startup类中没有改变任何内容

答案 1 :(得分:1)

有一个技巧可以做到这一点。你需要做这样的事情:

container.RegisterType< ChatHub >(new InjectionFactory(CreateChatHub));

......

然后创建一个私有方法CreateChatHub

private static object CreateChatHub(IUnityContainer container)
{
    return new ChatHub();
}

答案 2 :(得分:0)

1创建“ UnitySignalRDependencyResolver.cs”

public class UnitySignalRDependencyResolver : DefaultDependencyResolver
{
    protected IUnityContainer Container;
    private bool IsDisposed = false;

    public UnitySignalRDependencyResolver(IUnityContainer container)
    {
        if (container == null)
        {
            throw new ArgumentNullException("container");
        }

        Container = container.CreateChildContainer();
    }

    /// <summary>
    /// Gets the Autofac implementation of the dependency resolver.
    /// </summary>
    public static UnitySignalRDependencyResolver Current
    {
        get { return GlobalHost.DependencyResolver as UnitySignalRDependencyResolver; }
    }


    public override object GetService(Type serviceType)
    {
        if (Container.IsRegistered(serviceType))
        {
            return Container.Resolve(serviceType);
        }

        return base.GetService(serviceType);
    }

    public override IEnumerable<object> GetServices(Type serviceType)
    {
        if (Container.IsRegistered(serviceType))
        {
            return Container.ResolveAll(serviceType);
        }

        return base.GetServices(serviceType);
    }

    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);

        if (IsDisposed)
        {
            return;
        }

        if (disposing)
        {
            Container.Dispose();
        }

        IsDisposed = true;
    }
}

2。将解析器添加到Owin管道

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
         // Get container
        IUnityContainer container = UnityConfig.Container;

        // Create resolver
        var resolver = new UnitySignalRDependencyResolver(container);

        // Create SignalR Configuration
        var config = new HubConfiguration
        {
            Resolver = resolver
        };
        // Start SignalR
        app.Map("/signalr", map =>
        {
            map.RunSignalR(config);
        });
    }
}

3。将依赖项注入控制器的构造函数中

public class ValuesController : ApiController
{
    private readonly IMyDependency _myDependency;

    public ValuesController(IMyDependency myDependency)
    {
        _myDependency= myDependency;
    }
}