3

我是模拟和依赖注入的新手,需要一些指导。

我的应用程序使用典型的 N 层架构,其中 BLL 引用 DAL,UI 引用 BLL 但不引用 DAL。很直接。

可以说,例如,我有以下课程:

class MyDataAccess : IMyDataAccess {}
class MyBusinessLogic {}

每个都存在于一个单独的程序集中。

我想在 MyBusinessLogic 的测试中模拟 MyDataAccess。因此,我在 MyBusinessLogic 类中添加了一个构造函数来获取依赖注入的 IMyDataAccess 参数。但是现在当我尝试在 UI 层上创建 MyBusinessLogic 的实例时,它需要对 DAL 的引用。

我想我可以在 MyBusinessLogic 上定义一个默认构造函数来设置一个默认的 IMyDataAccess 实现,但这不仅看起来像代码味道,它实际上并没有解决问题。我仍然在签名中有一个带有 IMyDataAccess 的公共构造函数。所以 UI 层仍然需要引用 DAL 才能编译。

我正在尝试的一种可能的解决方案是使用 IMyDataAccess 参数为 MyBusinessLogic 创建一个内部构造函数。然后我可以使用测试项目中的访问器来调用构造函数。但是还是有那种味道。

这里的常见解决方案是什么。我一定是做错了什么。我该如何改进架构?

4

3 回答 3

4

你可以像这样定义你的类:

public class MainForm : Form
{
    private readonly businessLogic;

    public MainForm(IBusinessLogic businessLogic)
    {
        this.businessLogic = businessLogic;
    }
}

public class BusinessLogic : IBusinessLogic
{
    private IDataLayer dataLayer;

    public BusinessLogic(IDataLayer dataLayer)
    {
        this.dataLayer = dataLayer;
    }
}

public class DataLayer : IDataLayer
{
    public DataLayer(string connectionString)
    {
    }
}

请注意这里的主窗体如何不知道 DAL。现在我们确实需要一段知道所有类的代码,以便它们可以连接在一起。这通常在应用程序开始时完成:

public static void Main(string[] args)
{
   var dataLayer = new DataLayer("foo");
   var businessLogic = new BusinessLogic(dataLayer);
   var mainForm = new MainForm(businessLogic);

   Application.Run(mainForm);
}

当然,这是一个简化的例子。如果在实践中你有几十个或几百个类,那么这种启动布线会变得非常庞大和复杂,尤其是在循环依赖发挥作用时。这就是为什么创建依赖注入框架来用 XML 配置文件、代码配置或 .NET 属性替换该代码的原因。基本思想是一样的。

.NET 的依赖注入框架示例:AutoFacCastleSpring.NETStructureMapNinjectManaged Extensibility Framework

于 2010-03-18T23:47:33.833 回答
2

我昨天回答了一个关于如何构建我认为可以解决您的问题的 .NET 解决方案的问题。

在我的回答中,您的关键点应该是没有一个“实现”程序集引用其他“实现”程序集。这应该可以解决您的关注点分离问题。

此外,该结构还几乎要求使用依赖注入,并且非常适合单元测试和模拟的使用。

我希望它有所帮助。

于 2010-03-18T23:19:12.820 回答
0

如果您想避免必须从 UI dll 引用数据访问 dll,那么您可以将数据访问接口/基类提取到第三个库中,并让其他两个都引用它。

于 2010-03-18T23:26:14.583 回答