犀牛模拟,依赖注入和关注点分离

时间:2010-03-18 23:03:05

标签: dependency-injection rhino-mocks n-tier-architecture separation-of-concerns

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

我的应用程序使用典型的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创建内部构造函数。然后我可以使用测试项目中的Accessor来调用构造函数。但仍然有那种气味。

这里有什么常见的解决方案。我一定是做错了。我怎样才能改进架构?

3 个答案:

答案 0 :(得分: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。< / p>

答案 1 :(得分:2)

answered昨天提出了一个关于如何structure a .NET solution我认为可以解决问题的问题。

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

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

我希望它有所帮助。

答案 2 :(得分:0)

如果你想避免从UI dll引用数据访问dll,那么你可以将数据访问接口/基类提取到第三个库中,并且另外两个引用它。