Przejdź do treści

DevStyle - Strona Główna
Autofac i open generic types: Application Events revisited

Autofac i open generic types: Application Events revisited

Maciej Aniserowicz

31 marca 2010

Backend

Ostatnio poznaję kontener DI Autofac i baaardzo mi się on podoba – nie tylko nazwa, funkcjonalność także. Ten post rozpoczyna paczkę kilku ciekawych (mam nadzieję:) ) postów pokazujących, jak przy pomocy Autofac zbudować “samoskładającą się” aplikację.

Dzisiaj na dobry początek wrócimy do koncepcji, którą zerżnąłem od Udiego a przedstawiłem w poście Application Events (tam tez więcej linków w temacie samych zdarzeń). W opisanym przeze mnie sposobie mechanizm ten wymagał ręcznej rejestracji każdego handlera za pomocą klasy ApplicationEventsManager, na przykład tak:

  1:  ApplicationEventsManager.OnEvent<UserForgotPassword>().UseHandler<SendReminder>();

Mając takie rejestracje w momencie wywołania zdarzenia:

  1:  ApplicationEventsManager.Raise(new UserForgotPassword(user));

Manager przejeżdża się po prostu po swojej wewnętrznej liście handlerów i wykonuje te, które potrafią dane zdarzenie obsłużyć:

  1:  public static class ApplicationEventsManager
  2:  {
  3:  	private static readonly IList<object> _handlers = new SynchronizedCollection<object>();
  4:  
  5:  	public static void Raise<TEvent>(TEvent e) where TEvent : IApplicationEvent
  6:  	{
  7:  		foreach (var handler in _handlers.OfType<Handles<TEvent>>())
  8:  		{
  9:  			handler..Handle(e);
 10:  		}
 11:  	}
 12:  	//...

(po więcej kodu i wyjaśnień zapraszam oczywiście do wspomnianej notki)

Działa, fajnie wygląda, daje dużą kontrolę, ale można by spróbować inaczej. Po co ręcznie rejestrować handlery? O tego właśnie mamy przecież kontenery DI/IoC! Na dobrą sprawę kod CAŁEJ klasy ApplicationEventsManager, pozbawionej instrukcji pozwalających na ręczną rejestrację, mógłby wyglądać tak:

  1:  public static class ApplicationEventsManager
  2:  {
  3:  	public static void Raise<T>(T e) where T : IApplicationEvent
  4:  	{
  5:  		foreach (var handler in Container.Resolve<IEnumerable<Handles<T>>>())
  6:  		{
  7:  			handler.Handle(e);
  8:  		}
  9:  	}
 10:  }

Nic prostszego! Co prawda takie coś nawet na miano “managera” nie zasługuje, ale…:).

Z Aufoaq wystarczy zaimplementować klasę modułu, która wykryje wszystkie implementacje handlerów z wykorzystaniem otwartych typów generycznych. Brzmi groźnie? To zobaczmy:

  1:  public class ApplicationEventsRegistrationModule : Module
  2:  {
  3:  	protected override void Load(ContainerBuilder builder)
  4:  	{
  5:  		builder
  6:  		.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
  7:  		.AsClosedTypesOf(typeof(Handles<>));
  8:  	}
  9:  }

I.. to wszystko! Taki moduł dodajemy do Autofac, a reszta dzieje się sama. Każdy handler w całym systemie (wszystkich załadowanych dllkach) będzie widoczny – dzięki metodzie RegisterAssemblyTypes. Piękne.

Po więcej info o open generic types odsyłam do Google’a.

Zobacz również