【问题标题】:Dependency Injection - Passing dependencies all the way down依赖注入 - 一直向下传递依赖
【发布时间】:2012-11-07 22:05:58
【问题描述】:

我有一个具有典型架构的 MVC 应用程序...

ASP.NET MVC 控制器 -> 人员服务 -> 人员存储库 -> 实体框架数据库上下文

我正在使用 Castle Windsor,我可以看到将它与 ControllerFactory 一起使用来创建具有正确依赖关系的控制器的好处。使用这种方法,Controller 会获得一个 Service 注入,而后者又知道如何构造正确的 Repository,而 Repository 又知道要使用的正确 DbContext。

windsor 配置是这样的...

dicontainer = new WindsorContainer();
dicontainer.Register(Component.For<IPersonService>().ImplementedBy<PersonService>());
dicontainer.Register(
    Component.For<IPersonRepository>().UsingFactoryMethod(
        () => new PersonRepository(new HrContext("connectionString"))));

这是正确的做法吗?我不喜欢UsingFactoryMethod,但是想不出别的办法。

另外,如果存储库需要服务层不需要的依赖项(比如 ILogger)怎么办?这是否意味着我必须将 ILogger 传递到服务层而不使用它。这似乎是一个糟糕的设计。我会很感激这里的一些指示。我已经阅读了大量文章,但没有找到一个具体的例子来验证我是否做对了。谢谢。

【问题讨论】:

    标签: asp.net-mvc dependency-injection castle-windsor


    【解决方案1】:

    我尽量避免使用工厂方法(正如你提到的,你觉得这很有趣)。为避免这种情况,您可以创建一个创建新 DbContext 的数据库会话对象。然后,您的存储库只需要获取 IDbSession 的实例并使用其 dbContext 属性。然后,您还可以轻松控制 IDbSession 对象的范围(不要使用单例,因为它不是线程安全的)。

    我想说明这一点,以便我可以使这一点更重要...让您的构造函数只接收在 DI 容器中注册的对象(构造函数中没有选项或配置)。选项和配置应该在类中读取/写入,其唯一目的是读取/写入这些值。如果所有类都遵循这个模型,那么你的 DI 注册就变得容易了,类可以在它们的构造函数中添加它们需要的任何依赖项。

    如果您尝试使用在构造函数中具有选项的第三方库,请将该类包装在您自己的类中,该类具有易于使用的构造函数并使用配置类来读取传递给第三方库所需的值.这种设计还在您的代码和第三方库之间引入了一层抽象,然后可以在必要时更轻松地交换(或存根)第三方库。

    【讨论】:

    • 感谢您的回复。我得到了关于创建一个类来包装 DbContext 的第一部分。不是 100% 确定第二部分。这可能是您的建议吗? 1. 将 DbContext 包装在一个 IDbSession 中,并将 IDbSession 传递给 Repository。 2. 与其将connectionString 传递给IDbSession,不如传递一个可以包装ConfigurationManager 的IConfigurationManager 去检索AppSettings。非常感谢。
    • 1.正确 2. 有点正确...它可以像纯粹包装 ConfigurationManager 一样通用,但我通常将其特定于配置类型并在管理器内部进行一些错误处理。 IDbConfigurationManager 之类的东西公开了一个 ConnectionString 属性,getter 在该属性中调用 .Net ConfigurationManager,但当它不在配置文件中或字符串格式错误时也会引发异常。消费者只需要调用一个属性,而不必知道任何硬编码的“Key”字符串。
    猜你喜欢
    • 2023-03-09
    • 1970-01-01
    • 2013-04-30
    • 1970-01-01
    • 2019-04-18
    • 2018-07-06
    • 2021-11-19
    • 1970-01-01
    相关资源
    最近更新 更多