2

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

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

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

在不详细介绍我们的 BL --> PL/UI 实现的情况下,让我们关注我们的 DAL,它通过自定义 serviceHost 后面的 EntityService 公开。我们的项目以一个简单的例子进行了如下布局:

项目.数据模型

  • 单个组件
  • 硬参考:无
  • 运行时分辨率:无
  • 一个为抽象类提供数据建模接口的通用库。即EntityData抽象类

Project.DataModel.[?]数据

  • 许多程序集:即 CityData、CustomerData 等
  • 硬参考:Project.DataModel
  • 运行时分辨率:无
  • 定义基于 EntityData 的单个或多个实体的组件

Project.DataModel.[?]DataConfiguration

  • 许多程序集:即 CityDataConfiguration、CustomerDataConfiguration 等
  • 硬引用:Project.DataModel.[?]Data、EntityFramework
  • 运行时分辨率:无
  • 为上一个程序集中定义的实体定义 EntityTypeConfiguration 的组件。

项目.数据访问

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

Project.ServiceModel.EntityDataService

  • 单个组件
  • 硬引用:Project.DataModel、Project.DataAccess
  • 运行时分辨率:无
  • 通过 EntityManager 类对 EntityData 对象提供 CRUD 操作的通用服务。

Project.ServiceModel.EntityDataServiceContract

  • 单个组件
  • 硬参考参考:Project.DataModel
  • 运行时分辨率:Project.DataModel.[?]Data
  • 暴露服务契约并且需要定义 ServiceKnownTypes 所以我们需要 EntityTypes 的运行时解析。

项目.ServiceHost

  • 单个组件
  • 硬引用:无
  • 运行时解析:Project.ServiceModel.[?]Service、Project.ServiceModel.[?]ServiceContract
  • 一个自定义的 ServiceHost,它将在运行时(通过配置或目录扫描)解析和加载各种服务,例如 EntityDataService。

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

在这种情况下,您将如何实施 DI。我真的无法确定如何以及在何处使用 DI 或 DI Container、Composition Root 等等。

非常感谢您的意见。

4

1 回答 1

-1

人们有办法让依赖注入过于复杂。如果 FirstClass 需要一个 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 子类中执行一些轻量级方法调用来使您的应用程序运行。

于 2012-06-07T03:12:23.500 回答