Başlıca C # DI / IoC çerçeveleri nasıl karşılaştırılır? [kapalı]


308

Kutsal savaş bölgesine girme riski altında, Bu popüler DI / IoC çerçevelerinin güçlü ve zayıf yanları nelerdir ve kolayca en iyisi olarak düşünülebilir mi? ..:

  • Ninject
  • Birlik
  • Castle.Windsor
  • Autofac
  • StructureMap

Burada listelemediğim C # için başka DI / IoC Çerçeveleri var mı?

Kullanım durumum bağlamında, bir istemci WPF uygulaması ve bir WCF / SQL hizmetleri altyapısı oluşturuyorum, kullanım kolaylığı (özellikle açık ve özlü sözdizimi açısından), tutarlı belgeler, iyi topluluk desteği ve performans önemli faktörlerdir benim seçimim.

Güncelleme:

Atıfta bulunulan kaynaklar ve yinelenen sorular güncel değil gibi görünüyor, tüm bu çerçeveler hakkında bilgi sahibi olan biri ortaya çıkabilir ve gerçek bir fikir verebilir mi?

Bu konudaki görüşlerin çoğunun taraflı olabileceğini anlıyorum, ancak birisinin tüm bu çerçeveleri incelemek için zaman ayırdığını ve en azından genel olarak nesnel bir karşılaştırmaya sahip olmasını umuyorum.

Bu daha önce yapılmadıysa kendi araştırmalarımı yapmaya hazırım, ancak bunun en azından birkaç kişinin zaten yapmış olduğu bir şey olduğunu varsaydım.

İkinci Güncelleme:

Birden fazla DI / IoC konteyneri ile deneyiminiz varsa, lütfen bunların artılarını ve eksilerini sıralayın ve özetleyin, teşekkür ederim. Bu, insanların yaptıkları tüm belirsiz küçük kapları keşfetme alıştırması değil, popüler (ve aktif) çerçeveler arasında karşılaştırmalar arıyorum.


1
[Ninject vs Unity for DI] ( stackoverflow.com/questions/1054801/ninject-vs-unity-for-di ) ile aynı soru , ancak takip zamanı olabilir.
Matthew Flaschen

2
[Windsor Kalesi, Birlik ve StructureMap'i Karşılaştırma] 'nın olası kopyası ( stackoverflow.com/questions/2216684/… )
Mauricio Scheffer

@slomojo: Olası kopya. stackoverflow.com/questions/4509458/ioc-comparisions-closed . Ayrıca yanıtta IoC'lerin popülerliğini gösteren bir bağlantı var. Şuna bir göz at.
Dhinesh

@chibacity - Ben kullandım ... 4 proje, ilk ikisi gerçekten temel, hiçbir sorun, ikinci iki, Unity yapıcı enjeksiyon, sürdürülebilirlik, okunabilirlik söz konusu olduğunda bize çok fazla sorun neden oldu. Unity'yi her ikisinden de söküp bitirdik ve StructureMap ile değiştirdik, yapıcı enjeksiyonu çok basitti, yapılandırma temiz ve bakım yapılabilirdi. Benim kişisel zamanımda AutoFac ile oynadım, ama onu iyi buluyorum, daha iyi anlamak için bazı belgelere ihtiyacım var. Gerisi sadece okuduğum şey hakkında yorum yapabilirim.
Phill

SSRS ile ilgili bir sorun vardı, sessizce başarısız oldu ve neden başarısız olduğunu anlayamadık, koddan adım attı, istisna belirsizdi. Çalışması için bir hafta çalıştık. Sonunda StructureMap'e taşındığımızda başka bir girişimimiz daha oldu ve birkaç dakika içinde 'ObjectFactory.WhatDoIHave ()' kullanarak montajlar AppDomain'e yüklenmeden önce IoC'nin inşa edildiğini öğrendik, böylece arayüzler asla betona kaydedilmedi türleri.
Phill

Yanıtlar:


225

Bu soruya kapsamlı bir cevap kitabımın yüzlerce sayfasını kapsıyor olsa da , hala üzerinde çalıştığım hızlı bir karşılaştırma tablosu:

Birkaç DIC arasındaki farkı açıklayan bir tablo


40
Kitabınızın MEAP'ini okudum ve Ninject'i neden bunun dışında bıraktığınızı merak ediyor musunuz?
Martin Owen

2
Kısmi yanıt burada bulunabilir: manning-sandbox.com/thread.jspa?threadID=38943
Mark Seemann

25
@Mark, bunun için teşekkürler, umarım cevabınız Ninject'i içerebilir (önemli, sadece onu çevreleyen yeni hype nedeniyle değil, aynı zamanda yeni dil özelliklerini kullanması nedeniyle.)
ocodo

3
Ninject, AutoFac'ya benzer olsa da, birçok yöntemdir, NUGET Ekibi ve en popüler indirilen IOC konteyneri tarafından kullanılır. Ben .NET kitap Mark's Bağımlılık Enjeksiyon değildi hayal kırıklığına uğradım. Endüstrinin görünümünde 2. baskı varsa, umarım bu kitabı kitaba dönüştürür. Ben de Unity, MEF (değil gerçek bir DI), Ninject veya StructurMap girmek, ben sadece bir sözleşme veya uzak konser karada henüz kullanımları spring.net veya AutoFac vb ... o
Tom Stickel

2
Unity 3.5 zaten sözleşmeye dayalı kaydı destekliyor: nuget.org/packages/Unity/3.5.1404 . Bir dezavantajı kaldırın ;-)
Vladimir Dorokhov

116

Başka bir performans karşılaştırmasıyla karşılaştım (son güncelleme 10 Nisan 2014). Aşağıdakileri karşılaştırır:

İşte gönderiden hızlı bir özet:

Sonuç

Ninject kesinlikle en yavaş konteynerdir.

MEF, LinFu ve Spring.NET, Ninject'ten daha hızlıdır, ancak yine de oldukça yavaştır. AutoFac, Catel ve Windsor geliyor, ardından StructureMap, Unity ve LightCore geliyor. Spring.NET'in sadece XML ile yapılandırılabilecek bir dezavantajıdır.

SimpleInjector, Hiro, Funq, Munq ve Dynamo en iyi performansı sunar, son derece hızlıdırlar. Bir deneyin!

Özellikle Basit Enjektör iyi bir seçim gibi görünüyor. Çok hızlıdır, iyi bir dokümantasyona sahiptir ve ayrıca müdahale ve genel dekoratörler gibi gelişmiş senaryoları da destekler.

Ayrıca Ortak Hizmet Seçici Kitaplığı'nı kullanmayı deneyebilir ve umarım birden fazla seçeneği deneyebilir ve sizin için en iyi olanı görebilirsiniz.

Siteden Ortak Hizmet Seçici Kitaplığı hakkında bazı bilgiler:

Kütüphane, IoC kapları ve servis bulucuları üzerinde bir soyutlama sağlar. Kütüphaneyi kullanmak, uygulamanın sert referanslara dayanmadan yeteneklere dolaylı olarak erişmesine izin verir. Umut, bu kütüphaneyi kullanarak, üçüncü taraf uygulamalar ve çerçeveler, kendilerini belirli bir uygulamaya bağlamadan IoC / Servis Konumundan yararlanmaya başlayabilir.

Güncelleme

13.09.2011: Funq ve Munq yarışmacılar listesine eklendi. Grafikler de güncellendi ve Spring.NET zayıf performansından dolayı kaldırıldı.

04.11.2011: " Basit Enjektör ekledi , performans tüm yarışmacıların en iyisi".


(Karşılaştırma Bağlantısını takip ederek) Hız farklılıklarını (artı temel özellikler matrisini) görmek son zamanlarda ilginç. Teşekkürler.
lko

Bu karşılaştırma o kadar güvenilir değil çünkü bildiğim kadarıyla Ninject'in hem Interception hem de XML yapılandırması için uzantıları var, ancak karşılaştırma bunu belirtmiyor.
Daniel

15
bu çok nicel bir karşılaştırmadır. dosya boyutu veya gereken bağımlılık sayısı gibi performans dışı özellikler ne olacak? Ayrıca, dokümantasyon kalitesi veya kullanılabilirlik gibi öznel önlemler de faydalı olacaktır. Demek istediğim hız dışında düşünülmesi gereken faktörler var.
FistOfFury

1
StructureMap'in yazarı Jeremy Miller gibi geçmişte söyledi ... başka kelimelerle ifade etme - Daha hızlı IOC kapları olduğundan emin olun, ancak tam bir özellik setinden yoksundurlar.
Tom Stickel


49

Philip Mat tarafından hazırlanan bu harika .Net DI konteyner karşılaştırma blogunu okuyun .

Üzerinde kapsamlı performans karşılaştırma testleri yapar;

O önerir AutoFac hızlı, küçük ve kullanımı kolay olarak ... Kabul ediyorum. Görünüşe göre Birlik ve Ninject testlerinde en yavaş olanlardır.


5
Sonrası için bir güncelleme var .Net DI Konteyner Hız Redux : alt satırda, ilk etapta Birlik alınan yanlış bir yaklaşım oldu. Yeni ölçümlerle Unity çok daha iyi görünüyor.
Volker von Einem

33

Feragatname: 2015'in başlarından itibaren Jimmy Bogard'ın IoC Container özelliklerinin harika bir karşılaştırması var , işte bir özet:

Karşılaştırmalı Kaplar:

  • Autofac
  • Ninject
  • Basit Enjektör
  • StructureMap
  • Birlik
  • Windsor

Senaryo şudur: Birden fazla alıcıya tek bir istek / yanıt veya bildirim gönderebileceğim bir arabirim, IMediator var:

public interface IMediator 
{ 
    TResponse Send<TResponse>(IRequest<TResponse> request);

    Task<TResponse> SendAsync<TResponse>(IAsyncRequest<TResponse> request);

    void Publish<TNotification>(TNotification notification)
        where TNotification : INotification;

    Task PublishAsync<TNotification>(TNotification notification)
        where TNotification : IAsyncNotification; 
}

Daha sonra temel bir istek / yanıt / bildirim kümesi oluşturdum:

public class Ping : IRequest<Pong>
{
    public string Message { get; set; }
}
public class Pong
{
    public string Message { get; set; }
}
public class PingAsync : IAsyncRequest<Pong>
{
    public string Message { get; set; }
}
public class Pinged : INotification { }
public class PingedAsync : IAsyncNotification { }

Jenerikler için konteyner desteği ile ilgili birkaç şeye bakmak ilgimi çekti:

  • Açık jenerikler için kurulum (IRequestHandler <,> kolayca kaydediliyor)
  • Açık jeneriklerin birden fazla kaydı için kurulum (iki veya daha fazla INotificationHandlers)

Genel varyans için kurulum (temel INotification için işleyicileri kaydetme / istek boru hatları oluşturma) İşleyicilerim oldukça basittir, sadece konsola çıktılar:

public class PingHandler : IRequestHandler<Ping, Pong> { /* Impl */ }
public class PingAsyncHandler : IAsyncRequestHandler<PingAsync, Pong> { /* Impl */ }

public class PingedHandler : INotificationHandler<Pinged> { /* Impl */ }
public class PingedAlsoHandler : INotificationHandler<Pinged> { /* Impl */ }
public class GenericHandler : INotificationHandler<INotification> { /* Impl */ }

public class PingedAsyncHandler : IAsyncNotificationHandler<PingedAsync> { /* Impl */ }
public class PingedAlsoAsyncHandler : IAsyncNotificationHandler<PingedAsync> { /* Impl */ }

Autofac

var builder = new ContainerBuilder();
builder.RegisterSource(new ContravariantRegistrationSource());
builder.RegisterAssemblyTypes(typeof (IMediator).Assembly).AsImplementedInterfaces();
builder.RegisterAssemblyTypes(typeof (Ping).Assembly).AsImplementedInterfaces();
  • Açık jenerikler: evet, dolaylı olarak
  • Çoklu açık jenerikler: evet, dolaylı olarak
  • Genel çelişki: evet, açıkça

Ninject

var kernel = new StandardKernel();
kernel.Components.Add<IBindingResolver, ContravariantBindingResolver>();
kernel.Bind(scan => scan.FromAssemblyContaining<IMediator>()
    .SelectAllClasses()
    .BindDefaultInterface());
kernel.Bind(scan => scan.FromAssemblyContaining<Ping>()
    .SelectAllClasses()
    .BindAllInterfaces());
kernel.Bind<TextWriter>().ToConstant(Console.Out);
  • Açık jenerikler: evet, dolaylı olarak
  • Çoklu açık jenerikler: evet, dolaylı olarak
  • Genel kontravaryans: evet, kullanıcı tarafından oluşturulan uzantılarla

Basit Enjektör

var container = new Container();
var assemblies = GetAssemblies().ToArray();
container.Register<IMediator, Mediator>();
container.Register(typeof(IRequestHandler<,>), assemblies);
container.Register(typeof(IAsyncRequestHandler<,>), assemblies);
container.RegisterCollection(typeof(INotificationHandler<>), assemblies);
container.RegisterCollection(typeof(IAsyncNotificationHandler<>), assemblies);
  • Açık jenerikler: evet, açıkça
  • Çoklu açık jenerikler: evet, açıkça
  • Genel karşıtlık: evet, dolaylı olarak (3.0 güncellemesiyle)

StructureMap

var container = new Container(cfg =>
{
    cfg.Scan(scanner =>
    {
        scanner.AssemblyContainingType<Ping>();
        scanner.AssemblyContainingType<IMediator>();
        scanner.WithDefaultConventions();
        scanner.AddAllTypesOf(typeof(IRequestHandler<,>));
        scanner.AddAllTypesOf(typeof(IAsyncRequestHandler<,>));
        scanner.AddAllTypesOf(typeof(INotificationHandler<>));
        scanner.AddAllTypesOf(typeof(IAsyncNotificationHandler<>));
    });
});
  • Açık jenerikler: evet, açıkça
  • Çoklu açık jenerikler: evet, açıkça
  • Genel çelişki: evet, dolaylı olarak

Birlik

container.RegisterTypes(AllClasses.FromAssemblies(typeof(Ping).Assembly),
   WithMappings.FromAllInterfaces,
   GetName,
   GetLifetimeManager);

/* later down */

static bool IsNotificationHandler(Type type)
{
    return type.GetInterfaces().Any(x => x.IsGenericType && (x.GetGenericTypeDefinition() == typeof(INotificationHandler<>) || x.GetGenericTypeDefinition() == typeof(IAsyncNotificationHandler<>)));
}

static LifetimeManager GetLifetimeManager(Type type)
{
    return IsNotificationHandler(type) ? new ContainerControlledLifetimeManager() : null;
}

static string GetName(Type type)
{
    return IsNotificationHandler(type) ? string.Format("HandlerFor" + type.Name) : string.Empty;
}
  • Açık jenerikler: evet, dolaylı olarak
  • Çoklu açık jenerikler: evet, kullanıcı tarafından oluşturulan uzantı ile
  • Genel kontravaryans: derp

Windsor

var container = new WindsorContainer();
container.Register(Classes.FromAssemblyContaining<IMediator>().Pick().WithServiceAllInterfaces());
container.Register(Classes.FromAssemblyContaining<Ping>().Pick().WithServiceAllInterfaces());
container.Kernel.AddHandlersFilter(new ContravariantFilter());
  • Açık jenerikler: evet, dolaylı olarak
  • Çoklu açık jenerikler: evet, dolaylı olarak
  • Genel kontravaryans: evet, kullanıcı tarafından oluşturulan uzantı ile

Mükemmel! Btw, yukarıdaki özet Windsor'u kaçırdı, ancak Jimmy'nin orijinal makalesinde mevcut.
Louis

Vay canına kimse daha önce bu konuda uyarmadı (: Ben windsor ekledim, teşekkürler @Louis
stratovarius

21

Aslında tonlarca IoC çerçevesi var. Her programcı kariyerinin bir noktasında bir tane yazmaya çalışıyor gibi görünüyor. Belki onu yayınlamak değil, içsel çalışmaları öğrenmek.

Ben şahsen autofac'ı tercih ediyorum çünkü oldukça esnek ve bana uygun bir sözdizimi var (her ne kadar tüm kayıt yöntemlerinin uzatma yöntemleri olduğundan nefret ediyorum).

Diğer bazı çerçeveler:


Merhaba @abatishchev! :) ... asıl fikir, üçüncü taraf ve yerleşik yöntemlerin aynı temelde olduğundan emin olmaktı; birçok "kayıt" yöntemleri ayrı olarak gemi var (örneğin RegisterControllers()MVC için) bu yüzden bu durumda tasarım değerli olduğunu düşündüm. (Bu 5+ yıl önce tasarlandı.)
Nicholas Blumhardt

1
@NicholasBlumhardt: Merhaba! :) Geç cevap verdiğim için üzgünüm, diğerleri arasında bildirim kayboldu. Aslında böyle bir tutarlılık uğruna bana mantıklı geliyor. Şimdi nasıl düşünüyorsun, nasıl tasarlarsın?
abatishchev

@abatishchev jgauffin ile aynı fikirde değilim. Uzatma yöntemleri uzatma için kapalı değil, uzatmadır. Yapmanız gereken her şeyi yapabilen çerçevenizin çekirdeğini yazarsınız ve uzantı yöntemleri ile bazı ek işlevler, belki bazı varsayılan yardımcılar sağlarsınız, ancak herkes kendi uzantılarını yazmakta özgürdür. Çerçeveniz genişletmek için uzatma yöntemlerini kabul ederse iyi bir çerçeve olduğunu söyleyebilirim .
t3chb0t

6

Şimdiye kadar bulduğum en iyi karşılaştırmaya baktıktan sonra:

Mart 2010'da alınan bir anketti.

İlgi duyduğum bir nokta, bir DI / IoC Çerçevesi kullanan ve onu beğenen / beğenmeyen kişilerin, Yapı Haritası'nın en üste çıktığı görülüyor.

Ankette ayrıca Castle.Windsor ve StructureMap en çok tercih edilen gibi görünüyor.

İlginçtir ki, Unity ve Spring.Net en çok sevilmeyen popüler seçenekler gibi görünüyor. (Birliği tembellikten (ve Microsoft rozeti / desteğinden) düşünüyordum, ancak şimdi Windsor Kalesi ve Yapısı Haritası'na daha yakından bakacağım.)

Tabii ki bu muhtemelen (?) Mayıs 2010'da yayınlanan Unity 2.0 için geçerli değildir.

Umarım başka biri doğrudan deneyime dayalı bir karşılaştırma sağlayabilir.


2
Birlik oldukça iyi. İhtiyaç duyulan şeylerin çoğunu kapsar, ancak bazı insanlar dairesel bağımlılıkları çözmekten şikayet eder. Onu seviyorum. İhtiyacım olan her şeyi yaparım.
Dmitri Nesteruk

Birçok geliştirici bile bilmeden Castle kullanıyor . NHibernate için varsayılan Ioc . (En azından dün indirilen FluentNHibernate i ile). Ben de bir NHibernate uygulanmasını gördüğünü kullandığı Linfu nstead
k3b

5

Bu metni yazarken listenizde olmayan linfu ve spring.net de dahil olmak üzere google kodunda net-ioc-frameworks karşılaştırması için bakın .

Spring.net ile çalıştım: Birçok özelliği var (aop, kütüphaneler, docu, ...) ve dotnet ve java dünyasında çok fazla deneyim var. Özellikler modülerleştirilmiştir, böylece tüm özellikleri almanız gerekmez. Özellikleri veritabanları soyutlama, loggingabstraction gibi ortak sorunların soyutlamalarıdır. ancak IoC konfigürasyonunu yapmak ve hatalarını ayıklamak zordur.

Şimdiye kadar okudum gelen: Eğer küçük veya orta ölçekli bir proje için chooseh olsaydı ioc yapılandırma yapılır ve c # hata ayıklanabilir beri ninject kullanırdım. Ama henüz onunla çalışmadım. büyük modüler sistem için ben soyutlama kütüphaneleri nedeniyle spring.net ile kalmak istiyorum.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.