2010-10-11 18 views
6

Poniższy kod służy wyłącznie do celów demonstracyjnych.Castle Windsor IOC: Przekazywanie parametrów konstruktora do komponentów potomnych

Powiedzmy, że mam 2 komponenty (businessService i dataService) i klasę interfejsu użytkownika.

Klasa UI wymaga usługi biznesowej, businessService potrzebuje usługi dataService, a usługa dataService korzysta z metody connectionString.

Formularz klasa UI muszę rozwiązać usługi biznesowe, więc piszę poniższy kod:

var service = container.Resolve<BusinessService>(new { dependancy = "con string 123" })); 

informuje, że Zależność jest parametrem konstruktora connectionString.

Ale powyższy kod nie działa, mówiąc, że usługa danych spodziewa się zależności, która nie była usatysfakcjonowana.

Nie można utworzyć komponent „dataService” ponieważ ma zależności być spełnione. dataService oczekuje na następujących zależności:

Klucze (komponenty z określonymi kluczami) - zależność, która nie została zarejestrowana.

Więc jako obejście Robię to:

var service = container.Resolve<BusinessService>(new { dataService = container.Resolve<IDataService>(new { dependancy = "123" }) }); 

Ale od projektowania, kodowania stylu i wielu perspektyw to nie jest dobry sposób to zrobić.

Proszę więc, jeśli możesz doradzić, dlaczego nie działa w prosty sposób lub masz lepsze obejście, prosimy o udostępnienie.

+0

Czy możesz podać krótką, ale kompletną definicję BusinessService, DataService i dependancy/connectionString, która się nie powiedzie? Usuń dowolny kod, który nie przyczynia się bezpośrednio do odtworzenia problemu. –

+0

Jest to prosta i bezpośrednia publiczna klasa –

+0

BusinessService {public BusinessService (DataService dataService) {}} –

Odpowiedz

6

Zachowanie, które widzisz, jest zgodne z projektem.

Istnieje kilka sposobów podejścia do problemu, w zależności od tego, jak dynamiczna jest wartość, którą chcesz przekazać.

The documentation wykonuje bardzo dobrą robotę, opisując go, więc nie będę tego powtarzać.

Aktualizacja

Dla jasności - Windsor nie przechodzi inline argumenty dół uchwałą rurociągu. Powód jest prosty - robienie tego pobiłoby abstrakcję. Kod wywołujący musiałby domyślnie wiedzieć, że twoja BusinessService zależy od DataService, która zależy od ciągu połączenia.

Jeśli koniecznie musisz to zrobić, nie mów tego wyraźnie. Dokładnie to robisz - jednoznacznie rozwiązaj zależność DataService od łańcucha połączenia i jawnie usuń BusinessService przekazując DataService jako zależność.

Żeby było bardzo wyraźne (i ładniejszy, a także używać) Sugeruję używając napisanego przez Fabrykę że zamiast bezpośredniego wywoływania pojemnik

public interface IFactory 
{ 
    IDataService ResolveDataService(string connectionString); 
    IBussinessService ResolveBussinessService(IDataService dataService); 
    // possibly release method for IBussinessService as well 
} 
+0

sprawdzone linku, ale poważnie nie mogę zrozumieć wht mówią, możemy char lub sthng mieć prostą odpowiedź –

+0

@moutasema my proste pytanie brzmi: kiedy rozwiązam komponent macierzysty, ale parametry wysyłania dla jego dziecka, czy to działa? @moutasema Czy pojemnik automatycznie przekazać params do komponentu dziecko? @kkozmic nie, inline argumenty nie są propagowane w dół rozdzielczości rurociągu –

+2

@Moutasem al-awa: w skrócie, próbujesz coś zrobić, że w 99% przypadków jest złą praktyką. Unikaj wywoływania 'Resolve()' bezpośrednio (ponieważ robisz lokalizację usługi, a nie wtrysk zależności) i zobaczysz poprawny sposób, aby to zrobić. –

1

Mam potrzebne, aby to zrobić podczas tworzenia przejściowych komponenty wymagają obiektu kontekstowego. Rozwiązanie Kiedyś było zastąpić klasę DefaultDependencyResolver tak, że ma przekazywać argumenty wbudowanych w dół uchwałą rurociągu.

public class ArgumentPassingDependencyResolver : DefaultDependencyResolver 
{ 
    protected override CreationContext RebuildContextForParameter(
     CreationContext current, Type parameterType) 
    { 
     if (parameterType.ContainsGenericParameters) 
     { 
      // this behaviour copied from base class 
      return current; 
     } 

     // the difference in the following line is that "true" is passed 
     // instead of "false" as the third parameter 
     return new CreationContext(parameterType, current, true); 
    } 
} 

Instancja tej klasy musi być przekazywane w, gdy pojemnik jest tworzony (inne klasy muszą być również przekazywane w bo nie ma wygodne konstruktor, że trwa tylko resolverowi zależnościach):

var container = new WindsorContainer(
    new DefaultKernel(
     new ArgumentPassingDependencyResolver(), 
     new NotSupportedProxyFactory()), 
    new DefaultComponentInstaller()); 
0

Tak, co żądasz jest możliwe, ale należy używać abstrakcyjnych fabryk przez Typed Factory Facility zamiast prośby o usługę bezpośrednio z pojemnika.

Z wpisywanych fabryk, wszystko co musisz zrobić, to określić interfejsy fabrycznych i Windsor zadba o realizacji dla Ciebie.

public interface IBusinessServiceFactory { 
    IBusinessService CreateBusinessService(string connString); 
} 

public interface IDataServiceFactory { 
    IDataService CreateDataService(string connString); 
} 

Państwo dodać siłownia i zarejestrować swój interfejs fabryk następująco:

container.AddFacility<TypedFactoryFacility>(); 
container.Register(Component.For<IDataServiceFactory>().AsFactory()); 
container.Register(Component.For<IBusinessServiceFactory>().AsFactory()); 

Twój może teraz ręcznie zdefiniować sposób parametr Runtime zostanie przeniesiony na dół wykres obiektu poprzez zdefiniowanie Dynamic Parameter w rejestracji BusinessService.

container.Register(Component.For<IBusinessService, BusinessService>() 
    .LifestyleTransient() 
    .DynamicParameters((k, d) => { 
     d["dataService"] = k.Resolve<IDataServiceFactory>.CreateDataService((string)d["connString"]); 
    })); 

Pamiętaj, że słownik klawisze trzeba dopasować nazwy parametrów w metodzie CreateBusinessService i BusinessService konstruktora.

Należy również upewnić, że LifestyleTransient jeśli zamierzają utworzyć nową instancję za każdym razem sposób fabryka jest tzw. (Domyślnie jest to singleton)

Powiązane problemy