2011-04-12 9 views
13

Próbuję wprowadzić zdarzenia domeny do projektu. Koncepcja jest opisana w poście Udi Dahan jest - http://www.udidahan.com/2009/06/14/domain-events-salvation/Korzystanie z funkcji Autofac z wydażeniami domeny

Oto kod zdarzenia domenę

public interface IDomainEvent { } 

public interface IHandleDomainEvents<T> where T : IDomainEvent 
{ 
    void Handle(T args); 
} 

public interface IEventDispatcher 
{ 
    void Dispatch<TEvent>(TEvent eventToDispatch) where TEvent : IDomainEvent; 
} 

public static class DomainEvents 
{ 
    public static IEventDispatcher Dispatcher { get; set; } 

    public static void Raise<TEvent>(TEvent eventToRaise) where TEvent : IDomainEvent 
    { 
     Dispatcher.Dispatch(eventToRaise); 
    } 
} 

Najważniejszą częścią jest wdrożenie IEventDispatcher że oddziela zdarzenie domeny z co musi się zdarzyć, gdy zdarzenie jest wywoływane. Sztuczka polega na podłączeniu tego złącza przez kontener. Oto moja próba

Kod Rejestrowanie wszystkich obsługi zdarzeń domeny ....

 var asm = Assembly.GetExecutingAssembly(); 
     var handlerType = typeof(IHandleDomainEvents<>); 

     builder.RegisterAssemblyTypes(asm) 
      .Where(t => handlerType.IsAssignableFrom(t) 
         && t.IsClass 
         && !t.IsAbstract) 
      .AsClosedTypesOf(handlerType) 
      .InstancePerLifetimeScope(); 

i rozwiązywania wszystkich procedur obsługi zdarzeń w dyspozytora. Problem polega na tym, że żadne procedury obsługi nie zostały rozwiązane.

public class EventDispatcher : IEventDispatcher 
{ 
    private readonly IContainer _container; 

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

    public void Dispatch<TEvent>(TEvent eventToDispatch) where TEvent : IDomainEvent 
    { 
     var handlers = _container.Resolve<IEnumerable<IHandleDomainEvents<TEvent>>>().ToList(); 
     handlers.ForEach(handler => handler.Handle(eventToDispatch)); 
    } 
} 

Nie rejestruję poprawnie procedur obsługi zdarzeń ani nie rozwiązuję ich. Jak sprawdzić, czy rejestracja działa?

Przykład kodu z obsługi

public class SendWebQuestionToCSO : IHandleDomainEvents<JobNoteCreated> 
{ 
    private readonly IConfig _config; 

    public SendWebQuestionToCSO(IConfig config) 
    { 
     _config = config; 
    } 

    public void Handle(JobNoteCreated args) 
    { 
     var jobNote = args.JobNote; 
     using(var message = new MailMessage()) 
     { 
      var client = new SmtpClient {Host = _config.SmtpHostIp}; 
      message.From = new MailAddress(_config.WhenSendingEmailFromWebProcessUseThisAddress); 
      ...... etc 
     } 
    } 
} 

UPDATE Po pewnym prób i błędów EventDispatcher działa ok! Jeśli ręcznie zarejestruję program obsługi, a następnie uruchomę zdarzenie domeny, to działa. Skanowanie/rejestracja zespołu jest moim problemem. Instrukcja kod rejestracyjny ...

builder.RegisterType<SendWebQuestionToCSO >().As<IHandleDomainEvents<JobNoteCreated>>(); 

Więc jak mogę skanować wszystkie zespoły dla wszystkich IHandleDomainEvents<> podano one wyglądać tak

public class SendWebQuestionToCSO : IHandleDomainEvents<JobNoteCreated> 

Odpowiedz

7

Jak zauważył Peter, problem z rejestracją był związany z klauzulą ​​Where().

Podczas skanowania zespoły Autofac filtry części automatycznie w oparciu o usługi można określić, więc byłoby równie poprawne po prostu użyć:

builder.RegisterAssemblyTypes(asm) 
    .AsClosedTypesOf(handlerType) 
    .InstancePerLifetimeScope(); 
+0

Perfect Nick! Nie mogę się doczekać nadchodzącego kursu! – CRG

+0

Ah, tak, nawet gładsza. Okradziono mi 15 przedstawicieli! –

+0

Hehe, jak tego potrzebujesz, panie L.;) mimo to dostałem mój głos. –

1

Problem z kodem skanowania zespołu podczas korzystania z IsAssignableFrom. Filtr zapyta: "czy instancja SendWebQuestionToCSO może zostać przypisana do zmiennej o numerze IHandleDomainEvents<>?" Odpowiedź jest oczywiście "nie", ponieważ nigdy nie można mieć zmiennej o otwartym typie ogólnym.

Sztuką byłoby sprawdzenie interfejsów implementowanych przez każdy typ i sprawdzenie, czy któryś z nich zamyka ogólny typ interfejsu otwartego. Oto skorygowany skaner:

var asm = Assembly.GetExecutingAssembly(); 
    var handlerType = typeof(IHandleDomainEvents<>); 

    builder.RegisterAssemblyTypes(asm) 
     .Where(t => t.GetInterfaces().Any(t => t.IsClosedTypeOf(handlerType))) 
     .AsImplementedInterfaces() 
     .InstancePerLifetimeScope(); 
+0

Witaj Peter, w jakiej przestrzeni nazw mogę znaleźć "IsClosingTypeOf" – CRG

+0

Czy chodziło Ci o IsClosedTypeOf? Wypróbowałem to i nie zadziałało.Jednak wyglądało to bardzo obiecująco! Wszelkie inne pomysły byłyby bardzo pomocne, z którymi borykałem się zbyt długo ... – CRG

+0

Sprawdziłem źródło na code.google.com hg/src/Source/Autofac/Util/ReflectionExtensions.cs i metoda rozszerzenia IsClosingTypeOf jest bardzo prosta, więc skopiowałem kod powodujący - .Where (t => t.GetInterfaces(). Any (i => i.IsGenericType && i.GetGenericTypeDefinition() == handlerType)). TO DZIAŁA!!! Najważniejsze pytanie brzmi: czy metoda rozszerzenia została zastosowana w wersji 2.4.5.724 .Net4? – CRG