为 IoC 提供一个包装器是个好主意吗?
我使用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
为此,开发了公共服务定位器项目。它是对 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 theControllerFactory
. 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:
如果您有很多库以及在这些库之上构建的很多应用程序,您最终会得到大量的 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.
优点是您可以轻松地交换 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/