我正在构建一个从头开始(在.NET中)供我公司使用的框架,我想为此解决方案创建依赖注入核心。因此,框架需要使用DI,应用程序也需要。很容易,但我真正想做的是不要让这个框架的消费者使用任何一个特定的DI容器。我希望他们可以自由选择Autofac,StructureMap,Ninject或其他任何他们想要的东西。我可以定义一个依赖解析的接口,如下所示:
public interface IDIContainerAdapter
{
T Resolve<T>();
object Resolve(Type type);
T TryResolve<T>();
object TryResolve(Type type);
}
理论上你可以有这样的东西:
public class AutofacDIContainerAdapter : IDIContainerAdapter
{
private readonly IContainer container;
public AutofacDIContainerAdapter(IContainer container)
{
this.container = container;
}
#region IDIContainerAdapter Members
public T Resolve<T>()
{
return container.Resolve<T>();
}
public object Resolve(Type type)
{
return container.Resolve(type);
}
public T TryResolve<T>()
{
T result;
if (container.TryResolve<T>(out result))
{
return result;
}
return default(T);
}
public object TryResolve(Type type)
{
object result;
if (container.TryResolve(type, out result))
{
return result;
}
return null;
}
#endregion IDIContainerAdapter Members
}
显然,在传递上面构造函数中定义的container
之前,类型的注册会发生。到目前为止一切都很好......应用程序将注册其特定类型。问题是框架还需要注册一些类型,这就是问题所在:
在世界上我应该如何让使用该框架的应用程序了解要注册的类型?首先,这听起来像是一个糟糕的设计......有些事情让人感觉不对劲;肯定应用程序不应该关心它。其次,无论如何都不容易做到......
然后我考虑使用特定的DI容器作为框架,并让开发人员为他们的应用选择他们想要使用的任何东西(如果有的话)。但是,我不喜欢2个单独的DI容器一起运行的想法,研究这个已经证实这不是一个好主意。
所以我不知道什么是最好的解决方案?我只是强迫每个人都使用我喜欢的容器吗?
答案 0 :(得分:3)
前一段时间我遇到了同样的问题,当时没有找到真正令人满意的解决方案。由于时间的限制,我在库之前停止工作的最后一点想法是使用TinyIoC进行内部组合(它具有明显的优势,只是你所包含的代码文件,而不是一个额外的程序集),并为图书馆的用户提供了自由选择自己的IoC容器。但正如你正确地说的那样,这并非没有问题。
从今天的角度来看,我认为有两个合理可行的选择:
由于该库是在公司内部使用,我认为将其锁定为 特定容器不应该是巨大的问题,因为那里 无论如何,对于哪个容器通常应该是一个共识 用于项目。与任何其他图书馆一样,您不会想要每一个 项目使用谷歌泡沫破灭的第一件事 在它开始的那天。看看不同的容器和他们的 功能并在全公司范围内做出明智的决定。 (我个人认为你做不到 Autofac出错了。)如果您有使用数字的现有代码 不同的容器,用你选择的容器替换它们 他们的使用并不困难。
即使您的库代码是可组合的,也可能会有一些 特定对象设置,这在正常使用中非常常见。在 在这种情况下,以“预先组合”的形式公开那些可能是有意义的 通过门面课程,如果有人有更具体的 要求,他们仍然可以从你的所有部分自己滚动 提供。例如,AutoFixture使用此方法使用非常简单,尽管其组件具有高度可组合性。
如果你仍然认为你真的需要一种与容器无关的方法来进行对象组合,你可能需要先查看Common Composition,然后再自己构建相同的东西。
答案 1 :(得分:0)
嗯,我知道这是一个古老的话题,但我想在这里给我2美分,因为我过去曾经实现了类似的东西。不幸的是,我不再拥有代码了,但是当我说它需要很多努力时相信我,并且现在想一想,我认为这是不值得的,因为IOC容器从未改变多年(它是温莎城堡,我们只更新了版本。)
无论如何,在放下一行代码之前,写下案例和风险。特别是:
这只是列举一些需要考虑的方面。 希望它有所帮助
答案 2 :(得分:-1)
我的想法是一个方法可以添加到接口说Register&lt; T&gt;(字符串类型),用于向DI Container添加注册。
在库中创建一个Configuration类,展示应用程序在其组合根目录中使用DIContaineradapter实现调用的方法。现在由于库中有app DIContaineradapter的句柄,所以在方法中调用register方法来注册所有与库相关的实例。因此,应用程序无需知道库需要注册哪些类型,除非他们需要在通过dicontaineradapter实现的库上调用方法。
通过这种方式,应用程序可以自由地强制执行自己的dicontainer,并且库也可以通过应用程序实现的dicontainer注册其类型