Click here to Skip to main content
15,885,546 members
Articles / Database Development / SQL Server
Article

NHibernate DaoFactory Exposer with Castle MikroKernel

Rate me:
Please Sign up or sign in to vote.
2.91/5 (4 votes)
2 Feb 2007CPOL2 min read 37.1K   23   7
How to create DaoFactory instances with Castle/MikroKernel in NHibernate applications

Introduction

In a previous CodeProject article, NHibernate Best Practices with ASP .NET, Generics and Unit Tests by Bill McCafferty, Core project contains DAO interfaces and domain objects while Data project contains implementation of DAO interfaces.

For performance reasons, since we do not want to iterate over collections to find a matching object, we use DAO and thus NHibernate to query for objects we are interested in. Data project contains a reference to Core project. We cannot add Data project as reference to Core project, as this will cause a circular reference and .NET does not allow us to use circular references. As a side effect or result of this restriction:

  • We explicitly have to pass DAO instances to our domain objects during construction, or
  • Set DAO property of our domain object with an instance of DAO object which has to be created explicitly.

These two methods cause presentation layer developers (WinForm or Web) to write some repetitive code like this:

C#
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;
}

We can do a favour to presentation layer developers by automatically initializing internal DAO objects. Below is a description of how we can achieve this.

Castle MikroKernel/Windsor

Castle MikroKernel is an inversion of control container that provides us with a very rich set of extensibility. You can find out more information about Castle/MikroKernel here.

In order to work with Castle MikroKernel:

  1. We need three assemblies from Castle Project:

    • Castle.Model

    • Castle.Windsor

    • Castle.MikroKernel 

  2. We have to specify IoC components in our App/Web.config like the example provided below:

    XML
    <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 Class Hierarchy

As you can see in the simplified model below, we work with three classes and one interface in this sample implementation.

  • DomainObject: This is our domain object that needs a Dao instance to query the database
  • IDaoFactory: Specifies which DAO objects are supported by the factory
  • DaoFactory: Implements IDaoFactory interface. Creates Dao instances on request
  • DaoFactoryExposer: Exposes a DaoFactory instance by using Castle/MikroKernel IoC. As soon as we get a DaoFactory instance, we will also be able to get any needed Dao instance as specified by IDaoFactory interface:

Sample image

DaoFactoryExposer

C#
/******************************************************************************
  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 Interface

C#
using System;
using System.Collections.Generic;
using System.Text;

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

IDaoFactory Implementation (DaoFactory)

C#
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

C#
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!");
      }
    }    
  }
}

History

  • 2nd February, 2007: Initial post

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Team Leader PragmaTouch
Turkey Turkey
- Software developer
- Has BS degree in Computer Engineering
- Has MBA degree
- Programmed with C, C++, Delphi, T-SQL and recently C#
- Little educational experience with Prolog
- Feel enthusiasm about NHibernate and LINQ
- Love to develop on Cuyahoga Web Framework
- Developer of PragmaSQL Editor
(Code Project Members Choice Winner for 2009 and 2010)
- Developed JiraTouch and MoodleTouch for iPhone
- PragmaTouch Lead (www.pragmatouch.com)

Comments and Discussions

 
GeneralPartial Trust Castle Windsor Pin
reach4thelasers1-May-07 2:27
reach4thelasers1-May-07 2:27 
GeneralGood approach Pin
Billy McCafferty6-Feb-07 3:00
Billy McCafferty6-Feb-07 3:00 
Ali,

Nice work on the overview here. I've been asked a couple of times how'd I'd do it myself but never took the time to give it a try. Ironically, Andrew, another poster in the messenges below, asked me a few days ago and I finally gave it a shot: http://devlicio.us/blogs/billy_mccafferty/archive/2007/02/05/inject-di-container-into-domain-objects-with-nhibernate.aspx[^]. (I didn't realize until this morning that you had posted an article a few days ago.) Anyway, as always, there are 1,000 ways to skin a cat and my approach is just one more to add to the mix. One difference I did try to include was exposing the entire DI/IoC container to the domain object, and not just the DaoFactory. It would be simple to open your approach up in this way as well. The downside to giving the entire DI container to the domain objects is that they then have access to pretty much anything and everything which can lead to further dependencies which need to be maintained. Anyway, nice work, and let me know if you have questions or suggestions about my approach as well.

Billy
GeneralRe: Good approach Pin
Ali Ozgur6-Feb-07 3:45
Ali Ozgur6-Feb-07 3:45 
GeneralAnother dependency? [modified] Pin
Andrew V. Melnichuk5-Feb-07 5:31
Andrew V. Melnichuk5-Feb-07 5:31 
GeneralRe: Another dependency? Pin
Ali Ozgur5-Feb-07 5:58
Ali Ozgur5-Feb-07 5:58 
GeneralRe: Another dependency? Pin
Andrew V. Melnichuk5-Feb-07 6:20
Andrew V. Melnichuk5-Feb-07 6:20 
GeneralRe: Another dependency? Pin
Ali Ozgur6-Feb-07 0:56
Ali Ozgur6-Feb-07 0:56 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.