fbpx
devstyle.pl - Blog dla każdego programisty
devstyle.pl - Blog dla każdego programisty
3 minut

Autofac i open generic types: Application Events revisited


31.03.2010

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.

0 0 votes
Article Rating
5 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Krzysztof Koźmic
14 years ago

Nie bylbym soba, gdybym nie wspomnial, ze Autofa nie jest tu wyjatkiem i Castle Windsor tez fantastycznie radzi sobie ze wspomnianym zagadnieniem, o czym nawet niedawno blogowalem ;)

procent
14 years ago

@Krzysztof Koźmic:
Nie wątpię:). Wczesniej znalem tylko Unity i postanowilem (w sumie także za sprawą twoich postów i tweetów) poszerzyc horyzonty. Kolejność: Autofac -> Ninject -> Castle.

reVis
14 years ago

Dość wygodna sprawa z tą automatyzacją. Ale jak to bywa ktoś już zauważył braki Unity i stąd np. http://autoregistration.codeplex.com/

r
r
14 years ago

AppDomain.CurrentDomain.GetAssemblies() ??
A co z assemblies, które nie są załadowane?
Tak z ciekawości chętnie zobaczę jakby to wyglądało ze skanowaniem np. folderu bin w ASP.NET.
StructureMap ma ponoć bardzo duże możliwości skanowania, natomiast Ninject ma na nim wzorowany tzw. extension.

procent
14 years ago

@r:
Rozwinięcie tej koncepcji przedstawiłem w kolejnym poście ( http://www.maciejaniserowicz.com/post/2010/04/01/Samobudujaca-sie-aplikacja-z-Autofac.aspx ), gdzie do AppDomain ładuję wszystkie pliki z rozszerzeniem dll.

Kurs Gita

Zaawansowany frontend

Szkolenie z Testów

Szkolenie z baz danych

Książka

Zobacz również