为 IoC 提供一个包装器是个好主意吗?

发布于 2024-10-04 15:30:35 字数 829 浏览 0 评论 0原文

我使用 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);
    }
}

我添加了包装器,假设我可能想在未来的某个时刻更改 IoC 容器。此时我认为这很糟糕。原因之一是:我无法在代码中使用 ObjectFactory 来做其他有趣的事情,我必须使用这个包装器。另一件事是:我们的代码实际上不必独立于 DependencyInjection 容器。

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

I have been using StructureMap for more than a year now. And all this time I used to have a wrapper class called IoC which looked like this

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

I added the wrapper assuming that I might want to change the IoC container at some point down the line. At this point I am thinking this is bad. One reason is: I cannot use ObjectFactory in my code to do other interesting things, I have to use this wrapper. The other thing is: Our code shouldn't really have to be independent of the DependencyInjection container.

What are the pros/cons of using this approach?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦开始←不甜 2024-10-11 15:30:35

为此,开发了公共服务定位器项目。它是对 DI 框架的抽象,它定义了一个非常类似于您的 IoC 类的接口。我什至开发了 Simple Service Locator 库;一个 DI 库,它是公共服务定位器接口的直接实现。

因此从这个意义上说,对 DI 框架进行抽象并不奇怪。然而,当正确(且完全)执行依赖注入时,其想法是相应地调整应用程序的设计,在应用程序根目录中配置容器,并且最好在应用程序中只有一个位置来组装类型(阅读:调用 GetInstance)。对于 ASP.NET MVC 应用程序,这将是 ControllerFactory。对于 ASP.NET WebForms 应用程序,您通常需要重写 PageHandlerFactory< /a>.

当您遵循这些规则时,没有理由使用这样的抽象,因为无论如何您只是在应用程序中的单个位置调用容器。但是,如果这对您来说不可行,则可以使用 公共服务定位器 或您自己的抽象作为替代方案。

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

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

For this reason the Common Service Locator project has been developed. It is an abstraction over DI frameworks and it defines an interface much like your IoC class. I even developed the Simple Service Locator library; an DI library that is a direct implementation of the Common Service Locator interface.

So in that sense, it's not weird to have an abstraction over DI frameworks. However, when doing Dependency Injection correctly (and completely), the idea is to adjust the design of your application accordingly, configure the container in the application root, and have preferably just a single place in the application were types are assembled (read: were GetInstance is called). For an ASP.NET MVC application, this would be the ControllerFactory. For ASP.NET WebForms application you would typically need to override a PageHandlerFactory.

When you play by these rules, there is no reason to use such an abstraction, because you just call the container at a single place in your application anyway. However, if that's not feasible for you, using either the Common Service Locator or your own abstraction is an alternative.

But please take a step back before you decide to let your code depend on an abstraction over your IoC library, because this causes a lot of problems and is seen as an anti-pattern in general. Calling back into the container from within your code:

  • Makes the code much harder to test.
  • Hides dependencies instead making the code harder to read and maintain.
  • Disables compile-time support.
  • Disallows your dependency graphs to be verified by a tool.
半世蒼涼 2024-10-11 15:30:35

如果您有很多库以及在这些库之上构建的很多应用程序,您最终会得到大量的 IoC 注册代码,这些代码会在所有这些应用程序中重复。

您可以让每个库负责向容器注册自身,但它必须了解特定的 IoC 实现。或者您可以按照您的建议创建一个 IoC 包装器,并让您的库负责通过 IoC 包装器注册自身。

If you have a lot of libraries and a lot of applications built on top of those libraries you'll end up with a large amount of IoC registration code which gets duplicated across all of those applications.

You could have each library responsible for registering itself with a container but then it has to know about a specific IoC implementation. Or you could do as you suggest and create an IoC wrapper and have your libraries responsible for registering themselves via the IoC wrapper.

请远离我 2024-10-11 15:30:35

优点是您可以轻松地交换 IOC 容器。缺点是您会失去 IOC 容器特有的任何功能。 MVC 涡轮机采用这种方法。查看它的源代码,了解它如何处理定位器。 http://mvcturbine.codeplex.com/

The pro is that you can swap IOC containers painlessly. The con is that you lose any functionality specific to an IOC container. MVC turbine uses this approach. Have a look at it's source to see how it handles the locator. http://mvcturbine.codeplex.com/

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文