2017-01-16 11 views
1

Я пытаюсь сделать простую инъекцию конструкторы с NHibernate Listners событий, вот пример:Dependency Injection с прослушивателями событий NHibernate

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 и tthat похоже, тоже не работает, я полагаю, что мне нужно установить его в конфигурации, а также как-то.

ответ

1

Выяснил это!

Для тех, кто хочет использовать инжекцию зависимостей с прослушивателями событий, 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> 

Затем, прежде чем строить сессионный завод просто позвоните .Configure ("путь к XML-файл") на вашем объекте NHibernate.Cfg.Configuration.

EDIT: Похоже, мы действительно можем зарегистрировать слушатель без instatiating его с помощью этого метода:

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

Я предлагаю вам задать свой ответ в качестве принятого - с маленьким тиканием ниже оценки. Я обновил мой, чтобы указать регистрацию, поскольку интерфейсы - это не путь, но, тем не менее, это было бы более очевидно, если бы ваш ответ пришел первым. –

+1

Кроме того, вы можете исправить это последнее предложение, когда оно читает *, используя '_container.ResolveOptional()', а не '_container.ResolveOptional()' * –

+0

Хорошо, это говорит, что я должен подождать, прежде чем принимать мои, как ответ. Спасибо за публикацию, хотя, как правило, сложно получить обратную связь по NHibernate. –

2

Вы, кажется, находитесь на правильном пути, так как official Autofac documentation указывает на this blog post, где единственный шаг - переопределить значение по умолчанию BytecodeProvider с предоставленным Autofac.

Я думаю, что вам не нужно устанавливать самих слушателей, используя cfg.SetListener.

EDIT: Мое предположение ниже не так, как в ответ Пакс Bisonica, так как она работала путем регистрации обработчиков событий в контейнере Autofac как их конкретных классов и не связанные с ними интерфейсы

При учете слушателей событий с Autofac, вы убедились, что вы зарегистрировали их как связанные интерфейсы? что-то вроде:

builder 
    .RegisterType<FormGeneratorUpdate>() 
    .As<IPostUpdateEventListener>(); 

Я спрашиваю, потому что я уверен, что NHibernate попытается решить проблему с интерфейсами.

+0

Я удалил вызов setlistener и убедился, что тип зарегистрирован autofac и вместо ломать его просто не вызывает событие –