Jakie są zalety i wady korzystania z Enterprise Library Unity w porównaniu z innymi kontenerami IoC (Windsor, Spring.Net, Autofac ..)?
Jakie są zalety i wady korzystania z Enterprise Library Unity w porównaniu z innymi kontenerami IoC (Windsor, Spring.Net, Autofac ..)?
Odpowiedzi:
Przygotowuję prezentację dla grupy użytkowników. Jako taki właśnie przeszedłem przez kilka z nich. Mianowicie: AutoFac, MEF, Ninject, Spring.Net, StructureMap, Unity i Windsor.
Chciałem pochwalić się przypadkiem 90% (wstrzyknięcie konstruktora, do którego i tak ludzie używają głównie IOC). Możesz sprawdzić rozwiązanie tutaj (VS2008)
W związku z tym istnieje kilka kluczowych różnic:
Każdy z nich ma również inne funkcje (niektóre mają AOP i lepsze gadżety, ale generalnie wszystko, czego chcę, aby IOC robił, to tworzenie i pobieranie obiektów dla mnie)
Uwaga: różnice między różnymi pobieranymi obiektami bibliotek można zanegować za pomocą CommonServiceLocator: http://www.codeplex.com/CommonServiceLocator
Pozostaje nam więc inicjalizacja, która odbywa się na dwa sposoby: za pomocą kodu lub konfiguracji XML (app.config / web.config / custom.config). Niektórzy obsługują oba, inni tylko jeden. Powinienem zauważyć: niektórzy używają atrybutów, aby pomóc IoC.
Oto moja ocena różnic:
Tylko inicjalizacja kodu (z atrybutami). Mam nadzieję, że lubisz lambdy. Kod inicjujący wygląda następująco:
IKernel kernel = new StandardKernel(
new InlineModule(
x => x.Bind<ICustomerRepository>().To<CustomerRepository>(),
x => x.Bind<ICustomerService>().To<CustomerService>(),
x => x.Bind<Form1>().ToSelf()
));
Kod inicjalizacji lub XML lub atrybuty. wersja 2.5 jest również bardzo lambda'y. Podsumowując, jest to jeden z moich ulubionych. Kilka bardzo interesujących pomysłów dotyczących wykorzystania atrybutów przez StructureMap.
ObjectFactory.Initialize(x =>
{
x.UseDefaultStructureMapConfigFile = false;
x.ForRequestedType<ICustomerRepository>()
.TheDefaultIsConcreteType<CustomerRepository>()
.CacheBy(InstanceScope.Singleton);
x.ForRequestedType<ICustomerService>()
.TheDefaultIsConcreteType<CustomerService>()
.CacheBy(InstanceScope.Singleton);
x.ForConcreteType<Form1>();
});
Kod inicjujący i XML. Niezła biblioteka, ale konfiguracja XML jest bardzo upierdliwa. Świetna biblioteka dla firmy Microsoft lub sklepów przy autostradach. Inicjalizacja kodu jest łatwa:
container.RegisterType<ICustomerRepository, CustomerRepository>()
.RegisterType<ICustomerService, CustomerService>();
XML tylko tak blisko, jak potrafię. Ale jeśli chodzi o funkcjonalność, Spring.Net robi wszystko pod słońcem, co może zrobić IoC. Ale ponieważ jedynym sposobem na ujednolicenie jest użycie XML, jest to generalnie unikane przez sklepy .net. Chociaż wiele sklepów .net / Java używa Spring.Net ze względu na podobieństwo między wersją .net Spring.Net i projektem Java Spring.
Uwaga : konfiguracja w kodzie jest teraz możliwa dzięki wprowadzeniu Spring.NET CodeConfig .
XML i kod. Podobnie jak Spring.Net, Windsor zrobi wszystko, co chcesz. Windsor to prawdopodobnie jeden z najpopularniejszych kontenerów IoC w okolicy.
IWindsorContainer container = new WindsorContainer();
container.AddComponentWithLifestyle<ICustomerRepository, CustomerRepository>("CustomerRepository", LifestyleType.Singleton);
container.AddComponentWithLifestyle<ICustomerService, CustomerService>("CustomerService",LifestyleType.Singleton);
container.AddComponent<Form1>("Form1");
Może łączyć XML i kod (z wersją 1.2). Ładna, prosta biblioteka IoC. Wydaje się, że podstawy nie wymagają większego zamieszania. Obsługuje zagnieżdżone kontenery z lokalnym określaniem zakresu komponentów i dobrze zdefiniowanym zarządzaniem czasem życia.
Oto jak go zainicjować:
var builder = new ContainerBuilder();
builder.Register<CustomerRepository>()
.As<ICustomerRepository>()
.ContainerScoped();
builder.Register<CustomerService>()
.As<ICustomerService>()
.ContainerScoped();
builder.Register<Form1>();
Gdybym miał dziś wybierać: prawdopodobnie wybrałbym StructureMap. Ma najlepszą obsługę funkcji języka C # 3.0 i największą elastyczność w inicjalizacji.
Uwaga : Chris Brandsma przekształcił swoją oryginalną odpowiedź w post na blogu .
O ile widziałem, są prawie takie same, z wyjątkiem kilku szczegółów implementacji tu i tam. Największą przewagą Unity nad konkurencją jest to, że jest dostarczany przez Microsoft, jest wiele firm, które boją się OSS.
Wadą jest to, że jest raczej nowy, więc może zawierać błędy, które starsi gracze już rozwiązali.
Powiedziawszy to, możesz to sprawdzić .
Stary wątek, ale ponieważ jest to pierwsza rzecz, którą Google pokazał mi, kiedy wpisałem unity vs spring.net ...
Spring robi teraz CodeConfig, jeśli nie lubisz konfiguracji XML
http://www.springframework.net/codeconfig/doc-latest/reference/html/
Ponadto Spring to znacznie więcej niż tylko kontener DI, jeśli spojrzysz na sekcję „Moduły” w dokumentacji, kontener DI jest podstawą ogromnego stosu rzeczy, które robi.
Popraw mnie, jeśli się mylę, ale myślę, że sam Autofac obsługuje konfigurację XML wymienioną w tym linku: Konfiguracja Autofac XML
Spring ma jedną cechę, że może wstrzyknąć parametry do konstruktora lub właściwości na podstawie nazwy lub pozycji parametru. Jest to bardzo przydatne, jeśli parametr lub właściwość jest typu prostego (np. Liczba całkowita, wartość logiczna). Zobacz przykład tutaj . Nie sądzę, aby to naprawdę nadrabiało niezdolność Springa do wykonania konfiguracji w kodzie.
Windsor również może to zrobić i może to zrobić w kodzie, a nie w konfiguracji. (popraw mnie, jeśli się mylę, przechodzę przez to, co tutaj słyszałem).
Chciałbym wiedzieć, czy Unity może to zrobić.
Jedna uwaga: Ninject to jedyny kontener IoC, który obsługuje kontekstowe iniekcje zależności (zgodnie z ich witryną internetową). Jednak ponieważ nie mam doświadczenia z innymi kontenerami IoC, nie mogę powiedzieć, czy to się zgadza.
Aby dodać moje 2 centy, wypróbowałem zarówno StructureMap, jak i Unity. Zauważyłem, że StructureMap jest słabo / błędnie udokumentowany, trudny do skonfigurowania i niezgrabny w użyciu. Podobnie wydaje się, że nie obsługuje scenariuszy, takich jak przesłonięcie argumentów konstruktora w czasie rozwiązywania, co było dla mnie kluczowym punktem użycia. Więc rzuciłem to i poszedłem z Unity i zrobiłem to, co chciałem w około 20 minut.
Osobiście używam Unity, ale tylko dlatego, że pochodzi od firmy Microsoft. Żałuję tej decyzji z jednego powodu: największa rzecz, jaką ma przeciwko niej, ma jeden duży „błąd”, który powoduje, że nieustannie rzuca wyjątki. Możesz zignorować wyjątki podczas debugowania. Jednak spowalnia swoją aplikację ogromnie jeśli natknąć się nim, ponieważ rzuca wyjątek jest kosztowna operacja. Na przykład, obecnie „naprawiam” ten wyjątek w jednym miejscu w moim kodzie, gdzie wyjątki Unity dodają dodatkowe 4 sekundy do czasu renderowania strony. Aby uzyskać więcej informacji i obejść, zobacz:
Czy można sprawić, aby Unity nie zgłaszał wyjątku SynchronizationLockException przez cały czas?