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

KWo*_*dra 8 dependency-injection ioc-container unity-container signalr 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());
Run Code Online (Sandbox Code Playgroud)

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

container.RegisterType<ChatHub>(new PerRequestLifetimeManager()); 
Run Code Online (Sandbox Code Playgroud)

但是,每当我运行我的应用程序并离开我的聊天页面时,我得到"依赖失败的解决方案"异常,而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;
    } ... }
Run Code Online (Sandbox Code Playgroud)

谢谢!

Mar*_*bad 17

分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);
    }
}
Run Code Online (Sandbox Code Playgroud)

第二.在运行Startup类之前创建Unity容器并注册依赖项解析程序

unityContainer = new UnityContainer();
var unityHubActivator = new UnityHubActivator(_unityContainer);
GlobalHost.DependencyResolver.Register(typeof(IHubActivator), () => unityHubActivator);
//register some types in container
WebApp.Start<Startup>(startOptions);
Run Code Online (Sandbox Code Playgroud)

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

public class MyHub : Hub
{
    public MyHub(Logger logger)
    {
        logger.Info("hub constructor");
    }
}
Run Code Online (Sandbox Code Playgroud)

注意.我的Startup类中没有任何改变


小智 1

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

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

......
Run Code Online (Sandbox Code Playgroud)

然后创建一个私有方法CreateChatHub

private static object CreateChatHub(IUnityContainer container)
{
    return new ChatHub();
}
Run Code Online (Sandbox Code Playgroud)

  • 这里的问题是我的 ChatHub 需要将参数作为构造函数的一部分注入。其中三个参数(ChatRepository、SignalRConnectionRepository 和 UnitOfWork)已在 Unity 中注册,但使用 PerRequestLifetimeManager 注册。但是,我认为 SignalR Hub 的生命周期与 PerRequestLifetimeManager 的配合不太好。我需要通过多种方式注册这些存储库吗?一种方式适用于我的 MVC 控制器,另一种方式适用于我的 SignalR 集线器? (2认同)