2009-10-10 27 views
5

Właśnie czytałem o inwersji kontroli (IOC) i to przeszkadzało mi, że wydaje się, że to sprawia, że ​​zarządzanie pamięcią jest bólem. Oczywiście wydaje się, że ioc jest używany głównie w środowiskach zbierających śmieci (Net, Java, Scripting), podczas gdy mój problem dotyczy ustawień innych niż gc.Czy odwrócenie kontroli i RAII mogą być ze sobą połączone?

Moim zmartwieniem jest to, że IOC jest w pewnym sensie przeciwko RAII, ponieważ oddzielamy czas życia zasobu od czasu życia obiektu. Czy to nie przeszkadza komuś innemu? I prawdziwe pytanie, jakie techniki można zastosować, aby wszystko przebiegło sprawnie?

+0

Zobacz również http://stackoverflow.com/questions/987761/how-do-you-reconcile-idisposable-and-ioc i http://unity.codeplex.com/Thread/View.aspx?ThreadId=38588 – TrueWill

Odpowiedz

3

Z tego powodu stworzyłem własny kontener IoC, który zwraca (w C#/.NET) jednorazowe owijki serwisowe, które po utylizacji "zrobią dobrze" w odniesieniu do usługi.

Be go:

  • nic nie robić, gdy:
    • Obiekt nie wykona IDisposable
    • Nie jest pojemnik o zasięgu (w tym przypadku pojemnik będzie śledzić i powrócić ten sam obiekt więcej niż jeden raz, a gdy pojemnik zostanie usunięty, obiekt też będzie)
    • Nie jest on łączony
    • To nie jest singleton -scoped (tak samo jak o zasięgu pojemnika, ale hierarchii kontenerów będzie przechowywać usługi o zasięgu singleton w najwyższej pojemniku)
  • utylizować usługi (ma zakres fabryczny i implementuje IDisposable)
  • Powrót to do puli

oznacza to, że cały kod, który korzysta z moich usług jest wewnątrz przy użyciu bloku, ale intencja jest bardziej jasne, przynajmniej dla mnie:

using (var service = container.Resolve<ISomeService>()) 
{ 
    service.Instance.SomeMethod(); 
} 

zasadniczo SA ys: rozwiąż usługę, wywołaj metodę SomeMethod na instancji usługi, a następnie pozbądź się usługi.

Ponieważ wiedza o tym, czy zlikwidować instancję usługi, nie jest dostępna dla konsumenta, istniał albo wybór ignorowania całkowicie implementacji IDisposable, albo pozbywanie się wszystkich usług, które implementują IDisposable. Nie było dla mnie dobrym rozwiązaniem.Trzecim wyborem było zawarcie instancji usługi w obiekcie, który wiedział, co zrobić z usługą po usunięciu opakowania.

+0

Czasami pisanie na klawiaturze 'IDisposable' staje się nieuniknione (jak w przypadku użycia' foreach' na typie, który implementuje użyteczną metodę 'GetEnumerator()', ale nie implementuje 'IEnumerable '), ale jest to poważny zapach, ponieważ zauważ, że klasa zawiera odniesienie do czegoś, co implementuje "IDisposable" nie zawsze oznacza, że ​​"jest właścicielem" obiektu, do którego się odnosi. – supercat

0

Pierwszą rzeczą, o której mogłem pomyśleć, to SmartPointers. I argumenty szablonu. Ale nie jestem pewien, czy argumenty z szablonu są liczone jako technika IOC, chociaż myślę, że powinny. Przynajmniej te mogą złagodzić pewne problemy z IOC, ale nie są całkowicie sprzedawane na pomysł.

1

Tak i nie. IoC nie oddziela czasu życia zasobu od czasu życia obiektu, oddziela zakres wywołania metody od czasu istnienia obiektu - bardzo często chcesz, aby obiekt, który zostałby zniszczony na końcu metody, istniałby do czasu wykonania innego wywołania IoC. Musisz albo przenieść miejscowych metod do zakresu klasy i upewnić się, że żadna metoda nie jest ponownie wprowadzona, albo przyjąć inne podejście, takie jak posiadanie dodatkowego "środowiska" przekazywanego dookoła, aby pozwolić obiektom na posiadanie przez nie i zniszczeniu. w kolejnych wywołaniach metod IoC. Każde podejście staje się dość skomplikowane, jeśli chcesz mieć system generowania zdarzeń ogólnego przeznaczenia - albo twoje modele będą musiały implementować jawną rekursję i samą iterację, albo twój prosty kod RAII C++ szybko staje się bardzo złożonym gniazdem wywołań zwrotnych - wystarczająco złożonym, że poddaję się w C++ i RAII rozpoczęto pracę nad kin.

Powiązane problemy