将依赖注入的类与容器一起传递到应用程序启动WinForm

时间:2015-12-17 02:26:03

标签: winforms dependency-injection ioc-container n-tier-architecture compositionroot

我正在开发一个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以上,那么这似乎是一个问题,那么我将超过5个参数传递给启动WinForm。如果我决定将名为AppDependencyInjection的自制依赖注入容器传递给WinForm而不是单独注入的类,我可以将要传入的参数限制为只有一个。如果我这样做,它将使表示层依赖于自制的依赖注入项目,从而使表示层依赖于BLL和依赖注入项目。这可以接受吗?我还能做些什么来适应应用程序中依赖注入类的未来增长?

1 个答案:

答案 0 :(得分:2)

  

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

如果你注入超过5个依赖项,那表明你的班级做得太多了;责任太多了。它违反了Single Responsibility Principle。如果发生这种情况,您就开始考虑将类拆分为多个较小的类。例如,您可以将某些依赖项及其逻辑分组到Aggregate Services,或者您可以将我们的表单拆分为多个较小的组件/控件。 Rembember:关键是构图。

  

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

你不应该这样做。这是一种称为服务定位器的模式,它具有many downsides。坚持依赖注入,只注入类直接需要的东西如果这很麻烦,例如因为类也有依赖性,你的代码/设计有问题(例如SRP违规)。

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

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

在你的情况下,你似乎处于中间位置。虽然依赖关系似乎来自一个常见的“依赖注入器”,但您仍然手动连接您的类而没有反射(即您明确地调用构造函数)。请注意,一旦开始使用反射,就可以使用其中一个已知的DI库了。