Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/google-chrome/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Dependency injection 防止实现细节泄漏到依赖项注入容器的设置中_Dependency Injection_Separation Of Concerns - Fatal编程技术网

Dependency injection 防止实现细节泄漏到依赖项注入容器的设置中

Dependency injection 防止实现细节泄漏到依赖项注入容器的设置中,dependency-injection,separation-of-concerns,Dependency Injection,Separation Of Concerns,有时我们可以用DI容器做一些巧妙的技巧,例如:自动绑定、管理单例、每个请求管理一个实例等等。这非常好,并且可以真正简化一些场景 我遇到的问题是,某个特定类的关注点现在泄漏到了应用层。如果一个类希望以一种特定的方式进行实例化和管理(例如,作为一个单例,或者每个http请求只进行一次),那么现在就由应用层来确保这一点 出现的一些问题: 1) 潜在的bug,因为应用程序可能会错误地设置DI绑定 2) 当开发人员想要实现一个包时,这可能会令人困惑,因为设置DI容器的规则不是由包本身提供的,因此必须在注释

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

我遇到的问题是,某个特定类的关注点现在泄漏到了应用层。如果一个类希望以一种特定的方式进行实例化和管理(例如,作为一个单例,或者每个http请求只进行一次),那么现在就由应用层来确保这一点

出现的一些问题:

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

2) 当开发人员想要实现一个包时,这可能会令人困惑,因为设置DI容器的规则不是由包本身提供的,因此必须在注释或附带的测试用例中记录(这并不理想)

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();
    }
}
公共类MyApplicationsInjectModule:NInjectModule
{
公共空荷载()
{
Bind().ToConstant(foothat应该是singleton.Instant);
Bind().To().AsSingleton();
Bind().To().InRequestScope();
}
}
我的经验仅限于NInject——也许其他一些DI容器可以更优雅地处理这个问题


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

依赖注入引入了灵活性,这种灵活性还带来了错误地编写对象图的额外风险。这是DI为数不多的缺点之一,与是否使用DI容器无关

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

甚至

2) 当开发人员想要实现一个包时,这可能会令人困惑,因为设置DI容器的规则不是由包本身提供的,因此必须在注释或附带的测试用例中记录(这并不理想)

这就是为什么最好的策略(在.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
进行注册。由于
条形图
构造函数静态地公布其所需的依赖项,自动布线可以启动,容器将能够自动解析IFoo

有了适当的约定,就不需要重新配置容器来向代码库添加新类型

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


同样,如果您在配置上使用约定,这将自动发生。

好的,那么您基本上是说:保持简单-不要尝试任何棘手的事情。