代码之家  ›  专栏  ›  技术社区  ›  mikesigs

Rhino模拟、依赖注入和关注点分离

  •  3
  • mikesigs  · 技术社区  · 16 年前

    我的应用程序使用的是一个典型的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创建一个内部构造函数。然后我可以使用测试项目中的访问器来调用构造函数。但还是有那种味道。

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

    3 回复  |  直到 14 年前
        1
  •  4
  •   Wim Coenen    16 年前

    您可以这样定义类:

    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依赖注入框架示例: AutoFac Castle , Spring.NET StructureMap , Ninject 以及 Managed Extensibility Framework .

        2
  •  2
  •   Community Mohan Dere    9 年前

    我 answered 昨天的一个问题是如何 structure a .NET solution 我认为这会解决你的问题。

    希望对你有帮助。

        3
  •  0
  •   Lee    16 年前

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

    推荐文章