Projektowanie, Programowanie, Codzienność – BeniaminZaborski.com

11 Styczeń 2015

Jak new ProxyGenerator() z Castle.DynamicProxy może zabić maszynę

Filed under: How Can I Take ... — Tags: , , — Beniamin Zaborski @ 18:55

Castle.DynamicProxy to fajna biblioteka do dynamicznego generowania obiektów proxy. Zwykle obiekt proxy przydaje się nam gdy chcemy wykonać dodatkową operację przed, po czy na wystąpienie błędu wykonania właściwej metody. Najbardziej trywialny przykład to logowanie błędów, ale można wyobrazić sobie także bardziej wysublimowane przykłady jak choćby zarządzanie transakcjami.
Przykładowy kod tworzący obiekt proxy dla naszego obiektu implementującego interfejs ISomeBusinessComponent (z metodą DoMagic) i aplikujący jeden prosty interceptor SomeInterceptor mógłby wyglądać tak:

ProxyGenerator proxyGenerator = new ProxyGenerator();
var componentProxy = proxyGenerator.CreateInterfaceProxyWithTarget(component, new SomeInterceptor());
componentProxy.DoMagic();

Pierwszy krok to utworzenie instancji ProxyGenerator. Następnie możemy wygenerować obiekt proxy i wykonać na nim metodę DoMagic. Nic wyszukanego – prosty przykład. Ale co jeśli chcielibyśmy intensywnie i w wielu miejscach aplikacji tworzyć obiekty proxy. Hmm … po prostu powyższy kod wstawilibyśmy w te miejsca gdzie powinien być wywołany. Co sprytniejsi ubraliby go nawet w jakąś metodę utilową. Zasymulujmy taki przypadek za pomocą pętli:

foreach (var component in components)
{
  ProxyGenerator proxyGenerator = new ProxyGenerator();
  var componentProxy = proxyGenerator.CreateInterfaceProxyWithTarget(component, new SomeInterceptor());
  componentProxy.DoMagic();
}

Kod na pierwszy rzut oka może i wygląda OK (wiem można przenieść instancjonowanie ProxyGenerator poza pętlę – to symulacja). W rzeczywistości przy każdym wywołaniu przebiegu pętli będziemy tworzyć nową instancję ProxyGenerator, a jest to kosztowna operacja jeśli chodzi o pamięć (tworzenie m.in. Assembly).
Rozwiązanie? W tej symulacji po prostu należałoby wynieść tworzenie obiektu proxyGenerator poza pętlę. Inaczej mówiąc prosi się tu o singleton dla ProxyGeneratora.

foreach (var component in components)
{
  ProxyGenerator proxyGenerator = ProxyGeneratorSingleton.Instance;
  var componentProxy = proxyGenerator.CreateInterfaceProxyWithTarget(component, new SomeInterceptor());
  componentProxy.DoMagic();
}

Odpowiednio częste wykonywanie tworzenia instancji ProxyGenerator potrafi skutecznie skonsumować całą dostępną pamieć operacyjną na naszej maszynie.

Działający przykład zamieszczam tutaj.

Dodaj komentarz »

Brak komentarzy.

RSS feed for comments on this post. TrackBack URI

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Log Out / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Log Out / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Log Out / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Log Out / Zmień )

Connecting to %s

Stwórz darmową stronę albo bloga na WordPress.com.

%d bloggers like this: