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

使用 NHSessionManager 处理多个 NHibernate 程序集

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.57/5 (4投票s)

2007年2月2日

CPOL

2分钟阅读

viewsIcon

33319

downloadIcon

221

本文介绍了如何配置 NHSessionManager 来使用多个 NHibernate 程序集。

引言

在 Bill McCafferty 的上一篇文章 NHibernate Best Practices with ASP.NET, Generics and Unit Tests 中,NHSessionManager 通过 App/Web 配置文件进行配置,只需与 NHibernate 核心程序集一起使用。由于 NHSessionManager 和其他程序集(Core、Data 和 Test)位于同一个解决方案中,这种简单的方式就足以满足所有实际需求。但为了代码重用,我们可以考虑将 NHibernate 实用程序类(NHSessionManagerDomainObjectNHGenericDao)和接口(IGenericDao)重新组织到一个单独的解决方案/项目中。在这种情况下,我们需要一种更通用的方式来指定 NHSessionManager 的配置。

另一篇文章 Using NHibernate with Multiple Databases 同样由 Bill McCafferty 撰写,是扩展 .NET 配置系统的很好例子。

扩展配置系统

我们需要一个配置节处理程序和配置元素规范,以便通过 App/Web 配置文件指定多个 NHibernate 程序集。

我们的目标是处理这样的配置节

  <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"/>
    <section name="nHibernateAssemblies" 
	type=" NHibernateSample.Common.Configuration.NHAssembliesSection, 
	NHibernateSample.Common"/>
  </configSections>
  
  <nHibernateAssemblies>
    <NhAssemblies>
      <clearAssemblies />
      <NhAssembly name="Core assembly 1" assembly="ProjectName1.Core"/>
      <NhAssembly name="Another core assembly" assembly="ProjectName2.Core"/>
    </NhAssemblies>
  </nHibernateAssemblies>

NHAssemblyElement

NHAssemblyElement 继承自 System.Configuration 命名空间中的 ConfigurationElement

NHAssemblyElement 类具有两个属性

  • Name 用于保存核心程序集的描述性名称
  • Assembly 用于保存我们希望 NHSessionManager 加载的程序集的名称
public class NHAssemblyElement : ConfigurationElement
{
  public NHAssemblyElement( )
  {

  }

  public NHAssemblyElement( string name, string assembly )
  {
    Name = name;
    Assembly = assembly;
  }

  [ConfigurationProperty("name", IsRequired = true, IsKey = true, 
	DefaultValue = "Not Supplied")]
  public string Name
  {
    get { return (string)this["name"]; }
    set { this["name"] = value; }
  }

  [ConfigurationProperty("assembly", IsRequired = true, DefaultValue = "Not Supplied")]
  public string Assembly
  {
    get { return (string)this["assembly"]; }
    set { this["assembly"] = value; }
  }
}

NHAssembliesCollection

NHAssembliesCollection 继承自标准 ConfigurationElementCollection 类。

[ConfigurationCollection(typeof(NHAssemblyElement))]
public class NHAssembliesCollection : ConfigurationElementCollection
{
  public NHAssembliesCollection( )
  {
    NHAssemblyElement element = (NHAssemblyElement)CreateNewElement();
    Add(element);
  }

  public override ConfigurationElementCollectionType CollectionType
  {
    get
    {
      return ConfigurationElementCollectionType.AddRemoveClearMap;
    }
  }

  protected override ConfigurationElement CreateNewElement( )
  {
    return new NHAssemblyElement();
  }

  protected override object GetElementKey( ConfigurationElement element )
  {
    return ((NHAssemblyElement)element).Name;
  }

  public NHAssemblyElement this[int index]
  {
    get
    {
      return (NHAssemblyElement)BaseGet(index);
    }
    set
    {
      if (BaseGet(index) != null)
      {
        BaseRemoveAt(index);
      }

      BaseAdd(index, value);
    }
  }

  new public NHAssemblyElement this[string name]
  {
    get
    {
      return (NHAssemblyElement)BaseGet(name);
    }
  }

  public int IndexOf( NHAssemblyElement assembly )
  {
    return BaseIndexOf(assembly);
  }

  public void Add( NHAssemblyElement assembly )
  {
    BaseAdd(assembly);
  }

  protected override void BaseAdd( ConfigurationElement element )
  {
    BaseAdd(element, false);
  }

  public void Remove( NHAssemblyElement assembly )
  {
    if (BaseIndexOf(assembly) >= 0)
    {
      BaseRemove(assembly.Name);
    }
  }

  public void RemoveAt( int index )
  {
    BaseRemoveAt(index);
  }

  public void Remove( string name )
  {
    BaseRemove(name);
  }

  public void Clear( )
  {
    BaseClear();
  }
}

NHAssembliesSection

NHAssembliesSection 继承自标准 ConfigurationSection,并实现配置文件中指定的节处理程序,如下所示

<section name="nHibernateAssemblies" 
	type=" NHibernateSample.Common.Configuration.NHAssembliesSection, 
	NHibernateSample.Common"/>

代码如下:

public class NHAssembliesSection : ConfigurationSection
{
  [ConfigurationProperty("NhAssemblies", IsDefaultCollection = false)]
  [ConfigurationCollection(typeof(NHAssembliesCollection), 
	AddItemName = "NhAssembly", ClearItemsName = "clearAssemblies")]
  public NHAssembliesCollection NHAssemblies
  {
   get
   {
    NHAssembliesCollection assembliesCollection = 
	(NHAssembliesCollection)base["NhAssemblies"];
    return assembliesCollection;
   }
  }
}

对 NHSessionManager 的小修改

NHSessionManager 中,我们必须稍微修改 InitSessionFactory() 方法。

Bill McCafferty 提供的原始版本通过以下代码实现了 NHibernate 程序集的加载

private void InitSessionFactory() 
{
 NHibernate.Cfg.Configuration cfg = new NHibernate.Cfg.Configuration();
 // The following makes sure the web.config contains 
 // a declaration for the HBM_ASSEMBLY appSetting
 if (ConfigurationManager.AppSettings["HBM_ASSEMBLY"] == null || 
     ConfigurationManager.AppSettings["HBM_ASSEMBLY"] == "") 
 {
  throw new ConfigurationErrorsException
	("NHibernateManager.InitSessionFactory: \"HBM_ASSEMBLY\" must be " +
    "provided as an appSetting within your config file. \"HBM_ASSEMBLY\" 
	informs NHibernate which assembly " +
    "contains the HBM files. It is assumed that the HBM files are embedded resources. 
	An example config " +
    "declaration is \" key="\" />");
 }
 
 cfg.AddAssembly(System.Configuration.ConfigurationManager.AppSettings["HBM_ASSEMBLY"]);
 sessionFactory = cfg.BuildSessionFactory();
}

上面的代码处理一个配置文件,如下所示

<appSettings>
 <add key="HBM_ASSEMBLY" value="NHibernateSample.Core"/>
</appSettings>

正如我在文章的介绍中提到的,使用此 NHSessionManager 实现,我们必须在每次想要处理另一个 NHibernate 程序集时更改 NHSessionManager 源代码并重新编译。

我们的替代 NHSessionManager InitSessionFactory 实现的代码如下

private void InitSessionFactory( )
{
  NHibernate.Cfg.Configuration cfg = new NHibernate.Cfg.Configuration();

  NHAssembliesSection nhAssembliesSection = 
	ConfigurationManager.GetSection("nHibernateAssemblies") as NHAssembliesSection;
  
  if(nhAssembliesSection == null)
  {
    throw new ConfigurationErrorsException
	("nHibernateAssemblies section not defined in application configuration!");
  }

  foreach(NHAssemblyElement element in nhAssembliesSection.NHAssemblies)
  {
    try
    {
      cfg.AddAssembly(element.Assembly);
    }
    catch (Exception e)
    {
      throw new Exception(" Can not add assembly! " + e.Message, e.InnerException);
    }
  }

  try
  {
    sessionFactory = cfg.BuildSessionFactory();
  }
  catch (Exception e)
  {
    throw new Exception(" Can not create session factory! " + 
	e.Message, e.InnerException);
  }
}

历史

  • 2007 年 2 月 1 日:初始发布
© . All rights reserved.