【问题标题】:Preventing implementation details leaking into setup of Dependency Injection Container防止实现细节泄漏到依赖注入容器的设置中
【发布时间】:2011-11-23 01:39:27
【问题描述】:

有时我们可以使用 DI 容器做一些巧妙的技巧,例如:自动绑定、管理单例、管理每个请求一个实例等。这很棒,并且可以真正简化一些场景。

我遇到的问题是某个特定类的关注点现在会泄露到应用程序层。如果一个类希望以特定方式实例化和管理(例如,作为单例,或每个 http 请求仅一次),那么现在由应用层来确保这种情况发生。

出现的一些问题:

1) 潜在的错误,因为应用程序可能会错误地设置 DI 绑定。

2) 当开发人员想要实现一个包时可能会造成混淆,因为设置 DI 容器的规则不是由包本身提供的,因此必须记录在 cmets 或随附的测试用例中(其中不理想)。

3) 如果类的实现发生变化,现在每个使用该类的应用程序都有责任更新其 DI 容器绑定。

以下是您可以使用 NInject 执行的一些示例绑定,它们都存在此问题:

public class MyApplicationsInjectionModule : NInjectModule
{
    public void Load()
    {
        Bind<IFoo>().ToConstant(FooThatShouldBeASingleton.Instant);

        Bind<IFoo>().To<FooThatShouldBeASingleton>().AsSingleton();

        Bind<IFoo>().To<FooThatShouldOnlyBeInstantiatedOncePerRequest>().InRequestScope();
    }
}

我的经验仅限于 NInject - 也许其他一些 DI 容器可以更优雅地处理这个问题。

在不放弃 DI 容器提供的功能的情况下,我们可以采取哪些策略来避免这些问题?

【问题讨论】:

    标签: dependency-injection separation-of-concerns


    【解决方案1】:

    依赖注入引入了灵活性,而这种灵活性也带来了错误组合对象图的额外风险。这是 DI 的(非常)少数缺点之一,与您是否使用 DI 容器无关。

    1) 潜在的错误,因为应用程序可能会错误地设置 DI 绑定。

    甚至with Poor Man's DI it's perfectly possible to compose an incorrect object graph

    2) 当开发人员想要实现一个包时可能会造成混淆,因为设置 DI 容器的规则不是由包本身提供的,因此必须记录在 cmets 或随附的测试用例中(其中不理想)。

    这就是为什么最好的策略(在 .NET 上)是采用基于约定的配置。基本上,您可以告诉容器扫描所有适当的程序集并针对它们实现的接口注册所有公共类。

    如果你坚持构造函数注入自动装配会为你处理剩下的事情。

    例如,假设您在程序集中定义了此类:

    public class Foo : IFoo
    {
        private readonly IBar bar;
    
        public Foo(IBar bar)
        {
            if (bar == null)
                throw new ArgumentNullException("bar");
    
            this.bar = bar;
        }
    
        // Use this.bar for something interesting in the class...
    }
    

    在另一个程序集中,你可能有

    public class Bar : IBar { }
    

    配置为扫描适当程序集的容器将找到Bar 并将其注册为IBar,它还将找到Foo 并将其注册为IFoo。由于Bar 构造函数静态通告其所需的依赖项,Auto-wiring 可以启动,容器将能够自动解析 IFoo

    有了适当的约定,您无需重新配置容器即可将新类型添加到您的代码库中。

    3) 如果类的实现发生变化,现在每个使用该类的应用程序都有责任更新其 DI 容器绑定。

    同样,如果您使用 Convention over Configuration,这将自动发生。

    【讨论】:

    • 好的,所以你基本上是在说:保持简单 - 只是不要尝试任何棘手的事情。
    猜你喜欢
    • 2013-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-17
    相关资源
    最近更新 更多