.net 通用DI容器包装器并与通用框架和应用程序一起使用

.net 通用DI容器包装器并与通用框架和应用程序一起使用,.net,dependency-injection,inversion-of-control,ioc-container,.net,Dependency Injection,Inversion Of Control,Ioc Container,我正在从头开始(在.NET中)构建一个供我的公司使用的框架,我想将依赖注入作为这个解决方案的核心。因此,框架需要使用DI,应用程序也需要使用DI。很简单,但我真正想做的是不要让这个框架的使用者使用任何一个特定的DI容器。我希望他们可以自由选择Autofac、StructureMap、Ninject或任何他们想要的东西。我可以为依赖项解析定义一个接口,如下所示: public interface IDIContainerAdapter { T Resolve<T>

我正在从头开始(在.NET中)构建一个供我的公司使用的框架,我想将依赖注入作为这个解决方案的核心。因此,框架需要使用DI,应用程序也需要使用DI。很简单,但我真正想做的是不要让这个框架的使用者使用任何一个特定的DI容器。我希望他们可以自由选择Autofac、StructureMap、Ninject或任何他们想要的东西。我可以为依赖项解析定义一个接口,如下所示:

public interface IDIContainerAdapter
    {
        T Resolve<T>();

        object Resolve(Type type);

        T TryResolve<T>();

        object TryResolve(Type type);
    }
公共接口IDIContainerAdapter
{
T解析();
对象解析(类型);
T TryResolve();
对象TryResolve(类型);
}
理论上,你可以有这样的东西:

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
    }
公共类AutofacDIContainerAdapter:IDIContainerAdapter
{
专用只读IContainer容器;
公共汽车集装箱适配器(IContainer集装箱)
{
this.container=容器;
}
#区域IDIContainerAdapter成员
公共事务解决方案
{
返回container.Resolve();
}
公共对象解析(类型)
{
返回容器。解析(类型);
}
公共T TryResolve()
{
T结果;
if(container.TryResolve(out结果))
{
返回结果;
}
返回默认值(T);
}
公共对象TryResolve(类型)
{
客观结果;
if(container.TryResolve(type,out结果))
{
返回结果;
}
返回null;
}
#endregion容器适配器成员
}
显然,类型的注册将在传入上述构造函数中定义的
容器之前进行。到现在为止,一直都还不错。。。这些应用程序将注册它们的特定类型。问题是框架还需要注册一些类型,这就是问题所在:

我到底该如何让使用该框架的应用程序知道要注册哪些类型?首先,对我来说,这听起来是个糟糕的设计。。有点不对劲;当然,应用程序不需要关心它。第二,无论如何这不是一件容易的事

我确实考虑了使用特定的DI容器来构建框架,让开发者选择他们想要使用的任何东西(如果有的话)。然而,我不喜欢两个独立的DI容器一起运行的想法,研究证实这不是一个好主意


所以我一直在想什么是最好的解决方案?我只是强迫每个人使用我喜欢的容器吗?

我不久前也遇到了同样的问题,当时没有找到真正令人满意的解决方案。在库的工作因时间限制而停止之前,我的最后一个想法是使用TinyIoC进行内部合成(它的显著优点是只包含一个代码文件,而不是一个附加程序集),并让库的用户自由选择自己的IoC容器。但正如你正确地说的那样,这并非没有问题

从今天的角度来看,我认为有两个合理可行的选择:

  • 由于这个库是在公司内部使用的,我想把它锁定在 特定的容器不应该是一个大问题,因为 无论如何,应该就通常使用哪个容器达成共识 用于项目。与其他任何图书馆一样,您不会想要每一个 该项目将使用谷歌出现泡沫的第一件事 在它开始的那天。看看不同的容器和它们的 特点,并在公司范围内做出明智的决策。(我个人认为你不能 如果您的现有代码使用了一个数字 将不同的容器替换为您应该选择的容器 这并不难,因为它们被正确地使用了

  • 即使您的库代码是可组合的,也可能会有一些 正常使用时非常常见的特定对象设置。在里面 在这种情况下,以“预先编写”的形式公开这些内容可能是有意义的 通过门面类,如果有人有更具体的 根据您的要求,他们仍然可以从您的所有零件中滚动自己的零件 提供。例如,AutoFixture使用此方法使使用非常简单,尽管其组件具有高度的可组合性


如果您仍然认为您确实需要一种容器无关的方法来进行对象合成,那么您可能希望在自己构建基本相同的东西之前先了解一下。

我的想法是,可以将一种方法添加到接口中,比如Register(字符串类型),用于将注册添加到DI容器中

在库中创建一个配置类,公开一个方法,该方法将由应用程序在其合成根目录中使用DIContaineradapter实现调用。现在,由于库在方法中具有app DIContaineradapter句柄,因此调用register方法来注册所有与库相关的实例。因此,应用程序不需要知道库需要注册哪些类型,只需要在通过dicontaineradapter实现的库上调用一个方法


通过这种方式,应用程序可以自由输入自己的双容器,并且库可以通过应用程序实现的双容器注册其类型。我知道这是一个老话题,但我想在这里给我2美分,因为我在过去实现过类似的东西。不幸的是,我已经没有代码了,但请相信我,我说这需要付出很多努力,现在回想起来,我认为这是不值得的,因为IOC容器多年来从未更改过(它是Castle Windsor,我们只更新了版本)

无论如何,在写下一行代码之前,先写下案例和风险。特别地:
  • 只创建一个寄存器方法是非常有限的。什么