StructureMap to najstarszy framework dependency injection dla .NET. Jak łatwo się domyślić, używamy go w celu implementowania wstrzykiwania zależności (artykuł Martina Fowlera ).
Pewien czas temu chciałem użyć go wraz z WCF. Dla webserwisu ServerService WCF wygenerował interfejs IServerServicePortType oraz klienta ServerServicePortTypeClient. Konfiguracja tego webserwisu znajdowała się w pliku Web.config.
Zdefiniowałem regułę dla StructureMap:
ObjectFactory.Configure( x =>
{
x.ForRequestedType<IServerServicePortType>().TheDefault
.Is.OfConcreteType<ServerServicePortTypeClient>();
});
która powinna spowodować, że pobranie za pomocą ObjectFactory.GetInstance<IServerServicePortType>() zwróci nam obiekt klienta.
Wszystko fajnie, tylko że StructureMap wybierał zły konstruktor tej klasy. Jako że konfiguracja znajdowała się w pliku Web.config, chciałem, żeby StructureMap tworzył klasę za pomocą konstruktora bezparametrowego – niestety próbował użyć innego, co powodowało błąd (brak argumentów dla tego konstruktora). Spójrzmy na wygenerowane konstruktory klasy ServerServicePortTypeClient:
public ServerServicePortTypeClient();
public ServerServicePortTypeClient(string endpointConfigurationName);
public ServerServicePortTypeClient(string endpointConfigurationName, string remoteAddress);
public ServerServicePortTypeClient(string endpointConfigurationName,
System.ServiceModel.EndpointAddress remoteAddress);
public ServerServicePortTypeClient(System.ServiceModel.Channels.Binding binding);
Wykorzystywany był drugi z argumentem endpointConfigurationName.
Nie tego oczekiwałem. Logiczne było, że zostanie wybrany konstruktor najlepiej pasujący do podanych argumentów – czyli brak argumentów spowoduje wybranie bezargumentowego. :-) Po pewnym czasie znalazłem rozwiązanie na blogu autora StructureMap.
ObjectFactory.Configure( x =>
{
x.SelectConstructor( () => new SoapPortTypeClient());
x.ForRequestedType().TheDefault.Is.OfConcreteType();
});
Pierwsze wyrażenie jest co najmniej ciekawe – nie tworzymy tutaj obiektu, tylko definiujemy lambdę, z której następne StructureMap odczyta, jakiego konstruktora powinien uzyć. Sprytne!
Tags: .net, Dependency Injection, StructureMap, wstrzykiwanie zależności
0
komentarzy