1

我正在开发一个 WinForms 应用程序,该应用程序已配置为典型的 3 层 UI、BLL 和 DAL。我创建了一个单独的项目作为启动项目。还创建了另一个项目作为自制的依赖注入容器,目的是执行所有依赖注入设置。自制的依赖注入容器由启动项目实例化,然后将实例化对象传递给第一个 WinForm。

自制的依赖注入容器实现如下所示:

public class AppDependencyInjection
{
    public BLL.DataServices.DepartmentDataServices BllDeptDataServices = null;
    private DAL.DataServices.DepartmentDataServices DalDeptDataServices = null;

    public BLL.ReportServices.RequestReports BllRequestReports = null;
    private DAL.ReportServices.RequestReports DalRequestReports = null;

    public AppDependencyInjection()
    {
        DalDeptDataServices = new DAL.DataServices.DepartmentDataServices();
        BllDeptDataServices = new BLL.DataServices.DepartmentDataServices(DalDeptDataServices);//inject actual implementations

        DalRequestReports = new DAL.ReportServices.RequestReports();
        BllRequestReports = new BLL.ReportServices.RequestReports(DalRequestReports);//inject actual implementations
    }
}

启动项目如下图所示:

static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    //instantiate dependent classes and inject into class constructors 
    AppDependencyInjection aDI = new AppDependencyInjection(); 

    //Pass objects with injected dependencies into app startup WinForm
    Application.Run(new MDIS.WinForms.UI.Form1(aDI.BllDeptDataServices, aDI.BllRequestReports));
}

接收 WinForm 使用注入的对象进行如下实例化:

public Form1(BLL.DataServices.DepartmentDataServices aBllDeptDataServices,
             BLL.ReportServices.RequestReports aBllRequestReports)
{
    InitializeComponent();
    BllDeptDataServices = aBllDeptDataServices;
    BllRequestReports = aBllRequestReports;
}

WinForm 在以下两个按钮单击事件中使用注入的对象:

private void btnGetAllDepartments_Click(object sender, EventArgs e)
{
    List<DepartmentDto> aDepartmentDtoList = BllDeptDataServices.GetAllDepartments();
}

private void btnGetAllRequests_Click(object sender, EventArgs e)
{
    List<RequestDetailDto> aRequestDetailDtoList = BllRequestReports.GetAllRequestDetail();
}

这目前没有太大问题,因为我只传递了 2 个注入的对象。但是,如果对象的数量增长到超过 5 个,这似乎是一个问题,那么我将向启动 WinForm 传递超过 5 个参数。如果我决定将名为 AppDependencyInjection 的自制依赖注入容器而不是单独的注入类传递给 WinForm,我可以将要传递的参数限制为一个。如果我这样做,它将使表示层依赖于自制的依赖注入项目,从而使表示层同时依赖于 BLL 和依赖注入项目。这可以接受吗?我还能做些什么来适应应用程序中依赖注入类的未来增长?

4

1 回答 1

2

但是,如果对象的数量增长到超过 5 个,这似乎是一个问题,那么我将向启动 WinForm 传递超过 5 个参数。

如果你注入超过 5 个依赖项,这表明你的类做的太多了;有太多的责任。它违反了单一职责原则。如果发生这种情况,您开始考虑将您的课程分成多个较小的课程。例如,您可以将某些依赖项及其逻辑分组到聚合服务中,或者您可以将我们的表单拆分为多个较小的组件/控件。记住:关键是构图。

我决定将名为 AppDependencyInjection 的自制依赖注入容器传递给 WinForm,而不是单独注入的类。

你不应该这样做。这是一种称为服务定位器的模式,它有很多缺点。坚持依赖注入,只注入一个类直接需要的东西 如果这变得很麻烦,例如因为一个类有太多的依赖关系,那么你的代码/设计就有问题(例如违反 SRP)。

另请注意,不建议创建自己的 DI 库。这样的库将缺少可用的 DI 库为您提供的许多重要功能,但与使用纯 DI(即手动连接对象图)相比没有任何优势。你失去了编译时支持,没有得到任何回报。

当您的应用程序很小时,您应该从 Pure DI 开始,一旦您的应用程序和 DI 配置增长到维护您的 Composition Root 变得很麻烦,您可以考虑切换到已建立的 DI 库之一。

就您而言,您似乎处于中间位置。尽管依赖项似乎来自一个常见的“依赖项注入器”,但您仍然需要手动手动连接您的类而无需反射(即,您正在显式调用构造函数)。请注意,一旦开始使用反射,就该使用已知的 DI 库之一了。

于 2015-12-17T07:18:23.060 回答