使用IoC高级功能和自己的抽象

Joh*_*ith 3 .net ninject inversion-of-control

我已经阅读了许多有关在开发中使用IoC容器的有趣文章.在许多情况下,作者建议我们编写自己的简单包装器,它隐藏了读取容器的接口,如Ninject,Castle.Windsor,Unity等.

包装器的实现看起来像这样(对于Ninject):

/// <summary>
/// Contains links for service contract and realization.
/// </summary>
public static class IoC
{
    static readonly IKernel kernel;
    static IoC()
    {
        kernel = new StandardKernel();
    }

    public static void RegisterService<T>(Type service)
    {
        kernel.Bind<T>().To(service);
    }

    public static T Resolve<T>()
    {
        return kernel.Get<T>();
    }
}
Run Code Online (Sandbox Code Playgroud)

好的,但是如何使用此模式的高级功能?例如,我喜欢使用像InRequestScope()或InSingletonScope()这样的生命周期管理修饰符,许多容器都支持这种修饰符.使用上面的模式,我可以丢弃ninject并使用15行实现.区别在哪里?

我还看了一下CommonServiceLocator试图找到丰富的包装器,但它与我的IoC类没有太大区别.现在我认为我不应该制作自己的自行车并直接使用全功能容器.你呢?

Mar*_*ann 6

您的应用程序代码应完全忽略DI容器的存在,无论哪一个.相反,需要依赖项的类应该通过Constructor Injection请求它们,如下所示:

public class Foo
{
    private readonly IBar bar;

    public Foo(IBar bar)
    {
        if (bar == null)
            throw new ArgumentNullException("bar");

        this.bar = bar;
    }

    public void SomeMethod()
    {
        // use this.bar from here...
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意Guard子句和readonly关键字的组合如何保护类的不变量.从Foo类的任何方法,this.Bar保证可用.

所有DI容器都了解这种设计模式,因此您可以让您选择的容器构成组合根中的整个应用程序图.从这里,您可以使用容器的所有高级功能,而无需担心代码库的其余部分与容器耦合.