使用NHibernate事件监听器进行依赖注入

时间:2017-01-16 03:20:59

标签: c# nhibernate autofac

我正在尝试使用NHibernate Event Listners进行简单的构造函数注入,这是一个例子:

    public class FormGeneratorUpdate : IPostUpdateEventListener
{
    private readonly IHostingEnvironment _env;

    public FormGeneratorUpdate(IHostingEnvironment env)
    {
        _env = env;
    }

    public void OnPostUpdate(PostUpdateEvent @event)
    {
        string typeName = @event.Entity.GetType().Name;
        dynamic entity = @event.Entity;
        string filePath =
            $"{_env.ContentRootPath}\\App_Data\\FormGenerator\\{typeName}\\{entity.Id}.json";

        File.Delete(filePath);

        string json = JsonConvert.SerializeObject(entity);
        using (FileStream fs = File.Create(filePath))
        {
            // Add some text to file
            Byte[] content = new UTF8Encoding(true).GetBytes(json);
            fs.Write(content, 0, content.Length);
        }
    }
}

我目前将NHibernate bytecodeProvider设置为autofac实现,如下所示:

    NHibernate.Cfg.Environment.BytecodeProvider =
            new AutofacBytecodeProvider(_container, new ProxyFactoryFactory(), new DefaultCollectionTypeFactory());

这在构建会话工厂时似乎工作得很好,但我的问题是如何在没有首先实例化的情况下使用NHibernate配置注册事件监听器?我可以注册它的每一种方式都需要我首先实例化对象:

cfg.SetListener(ListenerType.Update, new FormGeneratorUpdate());

由于构造函数不是空的,它会抛出一个错误......我试过用Autofac注册事件监听器,但这似乎也不起作用,我相信我必须在配置上设置它一些如何。

2 个答案:

答案 0 :(得分:2)

由于official Autofac documentation指向this blog post,您似乎走在正确的道路上,其中唯一的步骤是使用Autofac提供的默认BytecodeProvider覆盖默认cfg.SetListener

我认为你不应该使用builder .RegisterType<FormGeneratorUpdate>() .As<IPostUpdateEventListener>(); 自己设置听众。

编辑:根据The Pax Bisonica的回答,我的假设是错误的,因为它通过将Autofac容器中的事件处理程序注册为具体类而不是相关接口

使用Autofac注册事件监听器时,您是否确保将它们注册为关联接口?类似的东西:

{{1}}

我问,因为我确信NHibernate会尝试解决这些接口。

答案 1 :(得分:2)

想出来!!

对于那些想要在事件监听器中使用依赖注入的人来说,autofac通过具体类型而不是接口来解析它们。最初我正在注册所有事件监听器:

         builder.RegisterAssemblyTypes(assemblies)
                  .AssignableTo<IPostUpdateEventListener>()
                  .AsImplementedInterfaces()
                  .InstancePerLifetimeScope();

我需要做的就是像这样注册:

            builder.RegisterAssemblyTypes(assemblies)
                  .AssignableTo<IPostUpdateEventListener>()
                  .AsSelf()
                  .InstancePerLifetimeScope();

当AutofacObjectsFactory调用CreateInstance时,它会尝试使用事件侦听器的具体类型而不是接口类型来解析它。

对于那些感兴趣的人,我最后使用xml配置注册列表器,以避免在事件监听器上创建默认构造函数...

    <?xml version='1.0' encoding='utf-8'?>
<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">

  <!-- an ISessionFactory instance -->
  <session-factory>
    <event type="post-insert">
      <listener class="FastTrack.FormGenerator.Listeners.FormGeneratorCreate, FastTrack"/>
    </event>
    <event type="post-delete">
      <listener class="FastTrack.FormGenerator.Listeners.FormGeneratorDelete, FastTrack"/>
    </event>
    <event type="post-update">
      <listener class="FastTrack.FormGenerator.Listeners.FormGeneratorUpdate, FastTrack"/>
    </event>
  </session-factory>

</hibernate-configuration>

然后在构建会话工厂之前,只需在NHibernate.Cfg.Configuration对象上调用.Configure(&#34; path-to-xml-file&#34;)。

编辑:看起来我们可以实际注册听众而无需使用此方法进行实例化

config.SetListeners(ListenerType.PostUpdate, new[] { typeof(FormGeneratorUpdate).AssemblyQualifiedName });