为你的IoC提供一个包装好主意吗?

Kha*_*din 3 structuremap abstraction dependency-injection ioc-container wrapper

我已经使用StructureMap超过一年了.而且这段时间我曾经有一个名为IoC的包装类,看起来像这样

class IoC {
    public static T GetInstance<T>()
    {
        return (T)GetInstance(typeof(T));
    }
    public static IEnumerable<T> GetAllInstances<T>()
    {
        return ObjectFactory.GetAllInstances<T>();
    }

    public static IEnumerable GetAllInstances(Type type)
    {
        return ObjectFactory.GetAllInstances(type);
    }

    public static object GetInstance(Type type)
    {
        return ObjectFactory.GetInstance(type);
    }

    public static void Inject<T>(T obj)
    {
        ObjectFactory.Inject(obj);
    }
}
Run Code Online (Sandbox Code Playgroud)

我添加了包装器,假设我可能想在某个时候更改IoC容器.此时我觉得这很糟糕.一个原因是:我不能在我的代码中使用ObjectFactory做其他有趣的事情,我必须使用这个包装器.另一件事是:我们的代码不应该真正独立于DependencyInjection容器.

使用这种方法的优点/缺点是什么?

Ste*_*ven 6

因此,开发了Common Service Locator项目.它是DI框架的抽象,它定义了一个类似于你的IoC类的接口.我甚至开发了Simple Service Locator库; DI库,它是Common Service Locator接口的直接实现.

所以从这个意义上讲,对DI框架进行抽象并不奇怪.但是,当正确地(并且完全地)执行依赖注入时,想法是相应地调整应用程序的设计,在应用程序根目录中配置容器,并且最好只在应用程序中的一个位置组装类型(读取:GetInstance叫做).对于ASP.NET MVC应用程序,这将是ControllerFactory.对于ASP.NET WebForms应用程序,您通常需要覆盖PageHandlerFactory.

当您按照这些规则进行游戏时,没有理由使用这样的抽象,因为您只需在应用程序中的单个位置调用容器.但是,如果这对您来说不可行,则使用公共服务定位器或您自己的抽象是另一种选择.

但是,在您决定让代码依赖于IoC库的抽象之前,请退后一步,因为这会导致很多问题并且通常被视为反模式.从代码中调用容器:

  • 使代码更难以测试.
  • 隐藏依赖关系,而不是使代码更难以阅读和维护.
  • 禁用编译时支持.
  • 禁止通过工具验证您的依赖关系图.