NHibernate:如何为实体注入依赖关系

Byr*_*ahl 9 structuremap nhibernate

NHibernate 3.2/Fluent NHibernate 1.3/StructureMap 2.6.3 -

尝试将DDD作为架构策略,我通常不依赖于域实体.但是,我现在正在尝试向我的域实体添加更多行为,以便它们不会如此贫乏.一切顺利,直到我连接NHibernate.我有两个问题:

  1. NH需要一个无参数的构造函数,而我宁愿没有一个不应该使用的ctor.
  2. 当NH试图实例化我的实体时,它需要解析我的依赖关系,但我没有给NH任何可以做到这一点的东西.

我一直在网上阅读,但我发现的大部分(如果不是全部)例子已经过时(或者只是旧版).虽然NH阵营可能不赞成我正在做的事情,但我正在寻找NH的方式来做到这一点.

Byr*_*ahl 4

该解决方案最终实现了 NHibernate 的 IInterceptor。当您继承 EmptyInterceptor 并仅重写 Instantiate() 和 SetSession() 方法时,它实际上是一个非常简单的实现。这是我使用 StructureMap 的拦截器:

public class DependencyInjectionEntityInterceptor : EmptyInterceptor
{
    IContainer _container;
    ISession _session;

    public DependencyInjectionEntityInterceptor(IContainer container)
    {
        _container = container;            
    }

    public override void SetSession(ISession session)
    {
       _session = session;            
    }

    public override object Instantiate(string clazz, EntityMode entityMode, object id)
    {
        if (entityMode == EntityMode.Poco)
        {
            var type = Assembly.GetAssembly(typeof (SomeClass)).GetTypes().FirstOrDefault(x => x.FullName == clazz);
            var hasParameters = type.GetConstructors().Any(x => x.GetParameters().Any());
            if (type != null && hasParameters)
            {
                var instance = _container.GetInstance(type);

                var md = _session.SessionFactory.GetClassMetadata(clazz);
                md.SetIdentifier(instance, id, entityMode);
                return instance;
            }
        }
        return base.Instantiate(clazz, entityMode, id);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您所要做的就是告诉 NHibernate 使用您的拦截器:

public FluentConfiguration GetFluentConfiguration(IContainer container)
{
    return Fluently.Configure()
        .Database(MsSqlConfiguration.MsSql2008
                  .ConnectionString(c => c.FromConnectionStringWithKey("Database"))
                      .ShowSql())
        .Mappings(m => 
            m.AutoMappings.Add(AutoMap.AssemblyOf<SomeClass>()))
        .ExposeConfiguration(x => 
            x.SetInterceptor(new DependencyInjectionEntityInterceptor(container)));                
}
Run Code Online (Sandbox Code Playgroud)

当我研究这个时,有人建议将 SessionFactory 传递到拦截器类的 ctor 中。老实说,从会话管理的角度来看,这种方法会更好。