nTier 中的依赖关系注入 + 运行时解析

本文关键字:运行时 注入 关系 依赖 nTier | 更新日期: 2023-09-27 18:35:00

我一直在阅读依赖注入(Mark Seemann:.NET 中的依赖注入和各种文章(,以帮助我的团队开发基于 EntityFramework、WCF 和 WPF 的新 3 层应用程序。

我假设我们在每个层上都需要一个组合根,因为它们通过服务进行通信(DAL <-> WCF <-> BL <-> WCF <-> PL/UI(。

我们的要求之一是我们需要动态加载和配置 EF,以便在应用程序部署后可以更改/扩展模型。

在不详细介绍我们的 BL --> PL/UI 实现的情况下,让我们关注通过自定义服务主机后面的实体服务公开的 DAL。我们的项目有一个简单的例子,布局如下:

Project.DataModel

  • 单个组件
  • 硬参考:无
  • 运行时分辨率:无
  • 一个公共库,它为抽象类和数据建模提供了接口。 即实体数据抽象类

项目.数据模型.[?]数据

  • 许多程序集:即城市数据,客户数据等
  • 硬引用:Project.DataModel
  • 运行时分辨率:无
  • 定义基于实体数据的单个或多个实体的组件

项目.数据模型.[?]数据配置

  • 许多程序集:即CityDataConfiguration,CustomerDataConfiguration等
  • 硬参考:Project.DataModel.[?]数据,实体框架
  • 运行时分辨率:无
  • 为上一个程序集中定义的实体定义实体类型配置的组件。

Project.DataAccess

  • 单个组件
  • 硬引用:Project.DataModel,EntityFramework
  • 运行时解析:Project.DataModel.[?]数据,项目.数据模型。[?]数据配置
  • 通过 EntityManager(抽象(提供 DbContext 的数据访问库。在运行时,此程序集查看配置或目录,加载实体类型及其等效的实体类型配置,并动态创建模型。

Project.ServiceModel.EntityDataService

  • 单个组件
  • 硬引用:Project.DataModel,Project.DataAccess
  • 运行时分辨率:无
  • 一种通用服务,通过 EntityManager 类对实体数据对象提供 CRUD 操作。

Project.ServiceModel.EntityDataServiceContract

  • 单个组件
  • 硬引用引用:Project.DataModel
  • 运行时解析:Project.DataModel.[?]数据
  • 公开服务协定并需要定义 ServiceKnownType,因此我们需要 EntityType 的运行时解析。

项目服务主机

  • 单个组件
  • 硬参考:无
  • 运行时解析:Project.ServiceModel.[?]服务,项目.服务模型。[?]服务合同
  • 自定义服务主机,将在运行时(通过配置或目录扫描(解析和加载各种服务,如实体数据服务。

这感觉很像一个插件项目,我们在编译时知道的不多,程序集之间没有太多硬引用。

在这种情况下,您将如何实现 DI。我真的无法确定如何以及在何处使用 DI 或 DI 容器、组合根和很多。

非常感谢您的意见。

nTier 中的依赖关系注入 + 运行时解析

人们有办法使依赖注入过于复杂。如果 FirstClass 需要一个 ISecondClass 来工作,那么只要确保没有 ISecondClass 就无法构建它。组合根本质上是一个类,你可以遵循其依赖项到其他所有内容。确保你的接口都有注册的实例(单例生存期通常可以很好地完成工作(,实例化组合根,大多数东西应该"正常工作"。如果没有,则某些事情比需要的要复杂得多。

WizBang应用程序可能如下所示:

interface IThingDoerA
{
}
class ThingDoerA : IThingDoerA
{
}
interface IThingDoerB
{
}
class ThingDoerB : IThingDoerB
{
    private readonly IThingDoerA _tda;
    public ThingDoerB(IThingDoerA tda)
    {
        _tda = tda;
    }
}
interface IThingDoerC
{
}
class ThingDoerC : IThingDoerC
{
    private readonly IThingDoerA _tda;
    private readonly IThingDoerB _tdb;
    public ThingDoerC(IThingDoerA tda, IThingDoerB tdb)
    {
        _tda = tda;
        _tdb = tdb;
    }
}
// I am the composition root.
interface IWizBang
{
    public void StartApp();
}
class WizBang : IWizBang
{
    private readonly IThingDoerA _tda;
    private readonly IThingDoerC _tdc;
    public WizBang(IThingDoerA tda, IThingDoerC tdc)
    {
        _tda = tda;
        _tdc = tdc;
    }
    public void StartApp()
    {
        //TODO
        // _tda.Blah()
        // _tdc.Blah()
    }
}

就 WPF 而言,看起来您可以在 System.Windows.Application 子类中执行一些轻量级方法调用来运行您的应用程序。