65.9K
CodeProject 正在变化。 阅读更多。
Home

NHibernate DaoFactory Exposer (带 Castle MikroKernel)

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.91/5 (4投票s)

2007年2月2日

CPOL

2分钟阅读

viewsIcon

37891

如何在 NHibernate 应用程序中使用 Castle/MikroKernel 创建 DaoFactory 实例

引言

在之前的 CodeProject 文章中, Bill McCafferty 的 使用 ASP .NET、泛型和单元测试的 NHibernate 最佳实践Core 项目包含 DAO 接口和域对象,而 Data 项目包含 DAO 接口的实现。

出于性能原因,由于我们不希望迭代集合来查找匹配的对象,我们使用 DAO,因此使用 NHibernate 来查询我们感兴趣的对象。 Data 项目包含对 Core 项目的引用。 我们无法将 Data 项目作为对 Core 项目的引用,因为这会导致循环引用,并且 .NET 不允许我们使用循环引用。 作为此限制的副作用或结果

  • 我们必须在构造期间将 DAO 实例显式传递给我们的域对象,或者
  • 使用必须显式创建的 DAO 对象的实例设置我们的域对象的 DAO 属性。

这两种方法导致表示层开发人员(WinForm 或 Web)编写一些重复的代码,例如

public void DoSomething()
{
  // DaoFactory can be stored as variable in session (Web) 
  // or as a static variable (WinForm)
  IDaoFactory daoFactory = new DaoFactory();
  
  // This can also be stored as variable in session (Web) 
  // or as a static variable (WinForm)
  ISomeDomainObjectDao dao = daoFactory.GetSomeDomainObjectDao();
  
  //Method-1: Pass dao instance as a parameter in constructor
  SomeDomainObject domObj = new SomeDomainObject(dao);

  //Method-2: Set DAO property of the domain object with an instance of the DAO
  SomeDomainObject domObj = new SomeDomainObject();
  domObj.SomeDomainObjectDao = dao;
}

我们可以通过自动初始化内部 DAO 对象来帮助表示层开发人员。 以下是关于我们如何实现这一点的描述。

Castle MikroKernel/Windsor

Castle MikroKernel 是一个控制反转容器,它为我们提供了一组非常丰富的可扩展性。 您可以在此处找到有关 Castle/MikroKernel 的更多信息。

为了使用 Castle MikroKernel

  1. 我们需要来自 Castle Project 的三个程序集

    • Castle.Model

    • Castle.Windsor

    • Castle.MikroKernel

  2. 我们必须在 App/Web.config 中指定 IoC 组件,如下面的示例所示

    <configSections>
      <section name="nhibernate" type="System.Configuration.NameValueSectionHandler, 
    	System, Version=1.0.1.0,Culture=neutral, 
    	PublicKeyToken=b77a5c561934e089" />
      <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,
    	log4net, Version=1.2.9.0, Culture=neutral, 
    	PublicKeyToken=b32731d11ce58905" />
      <section name="castle" 
    	type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, 
    	Castle.Windsor" />
    </configSections>
    
    <castle>
        <components>
          <component
            id="SampleDaoFactory"
            service="Fully qualified namespace where IDaoFactory interface resides"
            type="Fully qualified namespace where IDaoFactory implementation resides">
          </component>
          <component
            id="AnotherSampleDaoFactory"
            service="Fully qualified namespace where IDaoFactory interface resides"
            type="Fully qualified namespace where IDaoFactory implementation resides">
          </component>
        </components>
      </castle>

DaoFactoryExposer 类层次结构

正如您在下面的简化模型中所看到的,我们在此示例实现中使用了三个类和一个接口。

  • DomainObject:这是我们的域对象,需要一个 Dao 实例来查询数据库
  • IDaoFactory:指定工厂支持哪些 DAO 对象
  • DaoFactory:实现 IDaoFactory 接口。 按需创建 Dao 实例
  • DaoFactoryExposer:通过使用 Castle/MikroKernel IoC 公开 DaoFactory 实例。 一旦我们获得 DaoFactory 实例,我们也将能够获得 IDaoFactory 接口指定的任何需要的 Dao 实例

Sample image

DaoFactoryExposer

/******************************************************************************
  File  : DaoFactoryExposer.cs
  Class : DaoFactoryExposer
  Description:

  Created By: Ali Özgür
  Created On: 31/01/2007 14:55:24
  Contact   : ali_ozgur@hotmail.com

  Revisions:
*******************************************************************************/

using System;
using System.Collections.Generic;
using System.Text;

using Castle.Windsor;
using Castle.Windsor.Configuration.Interpreters;

namespace Bilgi.SampleProject.Core
{
  /// <summary>
  /// This class exposes dao factory using Castle.Windsoe IoC 
  /// container.
  /// </summary>
  public class DaoFactoryExposer
  {
    private IDaoFactory _daoFactory = null;

    public DaoFactoryExposer( )
    {
    }

    public IDaoFactory DaoFactory
    {
      get
      {
        if (_daoFactory != null)
        {
          return _daoFactory;
        }
        else
        {
          IWindsorContainer container = new WindsorContainer(new XmlInterpreter());
          _daoFactory = container["SampleDaoFactory"] as IDaoFactory;

          if (_daoFactory == null)
          {
            throw new TypeLoadException("Can not load dao factory from container!");
          }

          return _daoFactory;
        }
      }
    }
  }
}

IDaoFactory 接口

using System;
using System.Collections.Generic;
using System.Text;

namespace Bilgi.SampleProject.Core
{
  public interface IDaoFactory
  {
    ISomeNeededDao GetSomeNeededDao( );    
  }
}

IDaoFactory 实现 (DaoFactory)

using System;
using System.Collections.Generic;
using System.Text;

namespace Bilgi.SampleProject.Data
{
  public class DaoFactory:IDaoFactory
  {
    ISomeNeededDao _someNeededDao = null;
    
    #region IDaoFactory Members

    public ISomeNeededDao GetSomeNeededDao( )
    {
      if (_someNeededDao == null)
      {
        _someNeededDao = new SomeNeededDao();
      }
      return _someNeededDao;
    }
    
    #endregion
  }
}

DomainObject

using System;
using System.Collections.Generic;
using System.Text;

namespace Bilgi.SampleProject.Core
{
  public class DomainObject
  {
    #region Dao related
    
    private DaoFactoryExposer _daoFactoryExposer = new DaoFactoryExposer();

    IDaoFactory _daoFactory = null;
    public IDaoFactory DaoFactory
    {
      get
      {
        if (_daoFactory == null)
        {
          return _daoFactoryExposer.DaoFactory;
        }
        else
        {
          return _daoFactory;
        }
      }
      set
      {
        _daoFactory = value;
      }
    }

    ISomeNeededDao _someNeededDao = null;
    public ISomeNeededDao SomeNeededDao
    {
      get
      {
        if (_someNeededDao == null)
        {
          return DaoFactory.GetSomeNeededDao();
        }
        else
        {
          return _someNeededDao;
        }
      }
      set { _someNeededDao = value; }
    }

    #endregion //Dao related    
    
    //Some method that needs SomeNeededDao instance
    public void AddOrder(Customer customer, Product product)
    {
      // Here SomeNeededDao instance is created automatically by using DaoFactoryExposer
      decimal customerBalance = SomeNeededDao.QueryCustomerBalance(customer);
      if(customerBalance <= 0 )
      {
        throw new Exception("Not enough balance!");
      }
    }    
  }
}

历史

  • 2007 年 2 月 2 日:首次发布
© . All rights reserved.