SQL Server 2000DBAWindows 2003Visual Studio 2005Windows 2000.NET 2.0SQL Server 2005C# 2.0中级开发Visual StudioSQL ServerWindows.NETC#
NHibernate DaoFactory Exposer (带 Castle MikroKernel)
如何在 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
-
我们需要来自
Castle
Project 的三个程序集 -
Castle.Model
-
Castle.Windsor
-
Castle.MikroKernel
-
我们必须在 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
实例
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 日:首次发布