【问题标题】:Using UnityContainer as SignalR Dependency Resolver使用 UnityContainer 作为 SignalR 依赖解析器
【发布时间】:2012-03-31 15:20:00
【问题描述】:

我使用 Unity 作为我的 DI 容器,但在解析 SignalR 集线器时我无法让它工作。有没有人在这方面取得成功?我尝试了以下方法:

    public class UnityDependencyResolver : DefaultDependencyResolver
    {
        private readonly IUnityContainer _Container;



     public UnityDependencyResolver (IUnityContainer container)
            {
                _Container = container;
                //edit to add
                container.RegisterInstance<IJavaScriptMinifier>(NullJavaScriptMinifier.Instance);

            }

        public override object GetService(Type serviceType)
        {
            return base.GetService(serviceType) ?? _Container.Resolve(serviceType);
        }

        public override IEnumerable<object> GetServices(Type serviceType)
        {
            return base.GetServices(serviceType) ?? _Container.ResolveAll(serviceType);
        }

    }

但我收到一条错误消息,表明它无法解析 SignalR.Infrastructure.IJavaScriptMinifier

【问题讨论】:

  • 您是否在 Unity 中注册了 IJavaScriptMinifier 的实现?
  • 我在发布此内容后尝试过,但感觉就像是 hack。 (我将编辑帖子以显示如何)。我没有明确使用它,它是一个 SignalR 接口。
  • 也许你没有在你的应用程序中明确使用它。但是,如果您的基础设施依赖于它并且 SignalR 使用 DependencyResolver 来获得 IJavaScriptMinifier 的实现,则您需要在您的容器中注册它。我不会在解析器的构造函数中注册它,而是在应用程序的应用程序根目录中与所有其他依赖项一起注册。
  • SignalR 需要很多东西,而 DefaultDependencyResolver 包括这些东西(例如 IHubLocator、IHubFactory 和许多其他东西)。我不必注册那些。我想这可能只是一个错误。不过,我真的很感谢你的 cmets :)
  • 抱歉,我忽略了当 DefaultDependencyResolver 无法提供给定服务时,您只使用 Unity 作为后备。默认解析器中是否有任何类型的 Initialize 例程不会被您的自定义解析器调用?

标签: unity-container signalr


【解决方案1】:

我有点困惑,为什么您尝试先进行基本解析,然后再进行统一解析器。通常,如果您要用自己的替换基本实现,两者都会解决,但您应该首先解决,以便返回覆盖类的实例。例如,假设您要覆盖 SignalR 中的 IConnectionIdFactory。您可以创建自己的类,从给定接口继承,然后将其注册到 Unity。然后你的依赖解析器应该能够解析给定的依赖并返回,永远不要接触 SignalR 解析器。我整理了一个小测试应用程序,我的依赖解析器如下所示:

依赖解析器:

public class UnityResolver : DefaultDependencyResolver
{
    private readonly IUnityContainer _container;
    public UnityResolver(IUnityContainer container)
    {
        _container = container;
    }

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

测试我们是否有解析路径是很重要的,因为Resolve 会在不存在时抛出异常。

为了完整起见,这里是实现:

ConnectionIDFactory:

public class ConnectionIdFactory : IConnectionIdFactory
{                
    public string CreateConnectionId(IRequest request)
    {            
        return Guid.NewGuid().ToString();
    }
}

注册:

public class Bootstrapper
{
    public static void Pre_Start()
    {
        Container.DefaultContainer.Instance.RegisterType(
            typeof(IConnectionIdFactory), 
            typeof(Repositories.ConnectionIdFactory), 
            null, 
            new Microsoft.Practices.Unity.ContainerControlledLifetimeManager());

        AspNetHost.SetResolver(new Resolvers.UnityResolver(Container.DefaultContainer.Instance));
    }
}

【讨论】:

  • 感谢您的回复。我最初是先检查我的容器,然后是基类,但一直遇到我提到的IJavaScriptMinifier 错误。我认为这可能与 Unity 有关,因为示例(使用 Ninject)似乎有效。最后我认为这可能是 SignalR 中的一个错误。
  • @timDunham 不,这不是 signalR 中的错​​误,如果无法解决,则返回 null,SignalR 会做正确的事情。您看到的错误来自 Unity,而不是来自 SignalR。如前所述,Unity 将在调用未注册的服务时引发异常。
【解决方案2】:

昨天我通过以下方式解决了这个问题:

注册容器:

    AspNetHost.SetResolver(dependencyResolver);
    DependencyResolver.SetResolver(dependencyResolver);

解析器:

    public class UnityDependencyResolver : DefaultDependencyResolver, IDependencyResolver
    {
        private readonly IUnityContainer _container;

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

        #region IDependencyResolver Members

        public override object GetService(Type serviceType)
        {
            try
            {
                return _container.Resolve(serviceType);
            }
            catch
            {
                return base.GetService(serviceType);
            }
        }

        public override IEnumerable<object> GetServices(Type serviceType)
        {
            try
            {
                return _container.ResolveAll(serviceType);
            }
            catch
            {
                return base.GetServices(serviceType);
            }
        }

        #endregion
    }

中心:

    public class Chat : Hub
    {
        [Dependency]
        public UserService _userService { get; set; }

        public void Send(string message)
        {                
            _userService.SomeMethod();                
        }
    }

完美运行!

【讨论】:

  • 使用全部捕获来捕获解析异常是不好的,并且会降低性能,最好先用 if 确定是否可以解析。
  • 感谢 Jan 的建议。今晚我会试试这个并给你反馈。
  • Gary.S -> 正确。感谢您的注意。
【解决方案3】:

在 Hub 中注入统一容器的另一种方法是创建自己的 HubActivator 尝试这个。 https://stackoverflow.com/a/30887576/3000736

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多