2012-01-23 13 views
6

Szukam naprawdę prostego i lekkiego kontenera IoC , którego źródło C# można włączyć do mojego własnego projektu (nie tworząc zewnętrznego odnośnika).Project-Embedded IoC Container

Powodem tego jest to, że piszę infrastrukturę i chciałbym dostarczyć pojedynczy plik .dll, bez żadnych dodatkowych zależności.

ja też nie chcę ILMerge mój zespół z zespołem IoC ..

myślałem o MEF, jakieś inne sugestie?

+0

Możesz chcieć oznaczyć ten tag .net, by uzyskać więcej sugestii. –

+1

Spójrz na to pytanie: http://stackoverflow.com/questions/2515124/whats-the-simplest-ioc-container-for-c jest przykładem online –

+6

Jeśli piszesz bibliotekę, nie powinieneś w ogóle używać kontenera DI: http://stackoverflow.com/questions/2045904/dependency-inject-di-friendly-library/2047657#2047657 –

Odpowiedz

3

Jeśli używasz .NET 4.0, masz MEF w zestawie.

Dla .NET 2 napisałem kiedyś coś podobnego za pomocą interfejsów i Reflection. Istnieje wiele samouczków opisujących ten proces. Nawet jeśli możesz użyć MEF, warto przetestować kilka samouczków do refleksji, ponieważ tak działa pod nim MEF.

Sprawdź również, czy pytanie this ma kilka dobrych odpowiedzi. TinyIoC wygląda jak pojedynczy plik źródłowy.

+0

Dzięki za TinyIoC. Wydaje się, że dokładnie to, czego szukałem. – dux2

0

Bardzo lubię Castle.Windsor który jest open source, więc można dodać odpowiednie pliki z kodem do projektu

+2

Windsor nie jest moją definicją lekkiego pojemnika. Zawiera około 4 złożeń i wiele plików/klas źródłowych. – dux2

0

To naprawdę nie jest takie trudne, aby rzucić swój własny zbiornik, w zależności od rodzaju potrzebnych funkcji. Bardzo łatwo jest jednak tworzyć nieszczelności, więc sądzę, że prawdopodobnie chciałbyś użyć przetestowanego i wypróbowanego rozwiązania.

MEF jest używany przez niektórych jako kontener, ale (godne uwagi) inni mówią, że MEF is not an IOC container, w istocie MEF został zaprojektowany jako architektura wtyczki, a nie kontener iniekcyjny zależności.

Biorąc pod uwagę to wszystko, polecam zanurzenie całego kodu źródłowego wybranego kontenera w aplikacji lub użycie narzędzia do scalenia zestawu w swoje własne. ILMerge to narzędzie, które może to zrobić, większość komercyjnych obfuscatorów może ci w tym pomóc. Jeśli budujesz komercyjną bibliotekę lub aplikację, zdecydowanie polecam używanie odpowiedniego obfuscatora.

+0

Jak stwierdziłem w moim pytaniu, jestem gotów osadzić kod źródłowy kontenera w moim własnym projekcie, ale szukam przetestowanego kontenera z minimalną liczbą plików i klas. Nie proszę o ILMerge. – dux2

+0

Jakie są wymagania dotyczące pojemnika? Jakiego rodzaju wsparcia cyklu życia potrzebujesz? Czy chcesz skonfigurować XML, płynny interfejs API konfiguracji czy jesteś zadowolony z prostej konfiguracji każdego typu? –

+0

Chciałbym skonfigurować kontener według kodu. Chciałbym wsparcia dla singleton i przejściowych cykli życia. – dux2

3

Jeśli nie potrzebujesz nic nadzwyczajnego, kontener DI może być bardzo krótki:

public class Container 
{ 
    private readonly Dictionary<Type,Func<Container,object>> factories; 
    private readonly Dictionary<Type,object> cache; 

    public Container() 
    { 
     this.factories = new Dictionary<Type,Func<Container,object>>(); 
     this.cache = new Dictionary<Type,object>(); 
    } 

    public void Register<TContract>(Func<Container,TContract> factory) 
    { 
     // wrap in lambda which returns object instead of TContract 
     factories[typeof(TContract)] = c => factory(c); 
    } 

    public TContract Get<TContract>() 
    { 
     var contract = typeof(TContract); 
     if (!cache.ContainsKey(contract)) 
     { 
      this.cache[contract] = this.factories[contract](this); 
     } 
     return (TContract)this.cache[contract]; 
    } 
} 

Które byłoby użyć tak:

var container = new Container(); 
container.Register<ICar>(c => new Car(
    c.Get<IEngine>(), c.Get<IWheel>())); 
container.Register<IWheel>(c => new Wheel()); 
container.Register<IEngine>(c => new Engine()); 

var car = container.Get<ICar>(); 

Jeszcze bardziej minimalistyczne byłoby zrobić zależność wtrysk bez pojemnika:

IWheel wheel = new Wheel(); 
IEngine engine = new Engine(); 
ICar car = new Car(engine, wheel); 

Jednak w przypadku złożonych wykresów obiektowych może szybko uzyskać kompilację w celu utrzymania prawidłowej kolejności budowy podczas refaktur. Kontener nie ma tego problemu.