Bagaimana perbandingan kerangka kerja C # DI / IoC utama? [Tutup]

308

Dengan risiko melangkah ke wilayah perang suci, Apa kekuatan dan kelemahan kerangka kerja DI / IoC yang populer ini, dan bisakah seseorang dengan mudah dianggap yang terbaik? ..:

  • Tidak ada
  • Kesatuan
  • Castle.Windsor
  • Autofac
  • StructureMap

Apakah ada Kerangka DI / IoC lain untuk C # yang belum saya daftarkan di sini?

Dalam konteks kasus penggunaan saya, saya sedang membangun aplikasi WPF klien, dan infrastruktur layanan WCF / SQL, kemudahan penggunaan (terutama dalam hal sintaksis yang jelas dan ringkas), dokumentasi yang konsisten, dukungan dan kinerja komunitas yang baik adalah semua faktor penting dalam pilihan saya.

Memperbarui:

Sumber daya dan pertanyaan rangkap yang dikutip tampaknya sudah ketinggalan zaman, dapatkah seseorang dengan pengetahuan tentang semua kerangka kerja ini maju dan memberikan beberapa wawasan nyata?

Saya menyadari bahwa sebagian besar pendapat tentang hal ini cenderung bias, tetapi saya berharap seseorang telah meluangkan waktu untuk mempelajari semua kerangka kerja ini dan setidaknya memiliki perbandingan objektif secara umum.

Saya cukup bersedia untuk melakukan penyelidikan sendiri jika ini belum dilakukan sebelumnya, tetapi saya berasumsi ini adalah sesuatu yang setidaknya sudah dilakukan beberapa orang.

Pembaruan Kedua:

Jika Anda memiliki pengalaman dengan lebih dari satu wadah DI / IoC, silakan beri peringkat dan rangkum pro dan kontra dari mereka, terima kasih. Ini bukan latihan untuk menemukan semua wadah kecil yang dibuat orang, saya mencari perbandingan antara kerangka kerja populer (dan aktif).

ocodo
sumber
1
Pertanyaan yang sama dengan [Ninject vs Unity for DI] ( stackoverflow.com/questions/1054801/ninject-vs-unity-for-di ), tetapi mungkin ini saatnya untuk tindak lanjut.
Matthew Flaschen
2
kemungkinan duplikat [Membandingkan Castle Windsor, Unity and StructureMap] ( stackoverflow.com/questions/2216684/… )
Mauricio Scheffer
@slomojo: Kemungkinan rangkap. stackoverflow.com/questions/4509458/ioc-comparisions-closed . Juga ada tautan yang menunjukkan popularitas IoC dalam jawabannya. Lihat itu.
dhinesh
@cibacity - Saya sudah menggunakannya di ... 4 proyek, dua yang pertama benar-benar dasar, tidak ada masalah, dua yang kedua, Unity menyebabkan kita begitu banyak masalah ketika datang ke injeksi konstruktor, rawatan, mudah dibaca. Kami akhirnya merobek Unity dari keduanya dan menggantinya dengan StructureMap, injeksi konstruktor mati sederhana, konfigurasi bersih dan terawat. Dalam waktu pribadi saya, saya telah bermain dengan AutoFac, tetapi saya merasa fiddly, perlu beberapa dokumentasi untuk memahaminya dengan lebih baik. Selebihnya saya hanya bisa mengomentari apa yang saya baca.
Phill
Salah satu masalah yang kami miliki adalah dengan SSR, itu gagal gagal dan melangkah melalui kode yang kami tidak tahu mengapa gagal, pengecualiannya ambigu. Kami menghabiskan waktu seminggu menulis di sekitar untuk membuatnya bekerja. Akhirnya ketika kami pindah ke StructureMap, kami mencoba lagi, dan dalam beberapa menit menggunakan 'ObjectFactory.WhatDoIHave ()' kami mengetahui bahwa IoC sedang dibangun sebelum majelis dimuat ke dalam AppDomain, sehingga antarmuka tidak pernah terdaftar dengan beton. jenis.
Phill

Jawaban:

225

Sementara jawaban komprehensif untuk pertanyaan ini memakan ratusan halaman buku saya , berikut adalah bagan perbandingan cepat yang masih saya kerjakan:

Tabel yang menjelaskan perbedaan antara beberapa DIC

Mark Seemann
sumber
40
Saya telah membaca MEAP dari buku Anda dan bertanya-tanya mengapa Anda meninggalkan Ninject darinya?
Martin Owen
2
Jawaban sebagian dapat ditemukan di sini: manning-sandbox.com/thread.jspa?threadID=38943
Mark Seemann
25
@Ark, terima kasih untuk ini, semoga jawaban Anda dapat mencakup Ninject (penting, bukan hanya karena hype baru di sekitarnya, tetapi juga karena itu menggunakan fitur bahasa baru.)
ocodo
3
Ninject sementara mirip dengan AutoFac banyak cara, ini digunakan oleh Tim NUGET, dan wadah IOC yang paling populer diunduh turun. Saya kecewa bahwa itu tidak ada dalam Mark's Dependency Injection di .NET book. Jika ada edisi ke-2 di tampilan industri, mudah-mudahan itu akan membuatnya menjadi buku. Saya bertemu dengan Unity, MEF (bukan DI nyata), Ninject, atau StructurMap, saya hanya belum mendapatkan kontrak atau pertunjukan jarak jauh yang menggunakan spring.net atau autofac dll ...
Tom Stickel
2
Unity 3.5 sudah mendukung pendaftaran berdasarkan konvensi: nuget.org/packages/Unity/3.5.1404 . Hapus satu kelemahan ;-)
Vladimir Dorokhov
116

Saya menemukan perbandingan kinerja lain (pembaruan terbaru 10 April 2014). Ini membandingkan yang berikut:

Berikut ini ringkasan singkat dari pos tersebut:

Kesimpulan

Ninject jelas merupakan wadah paling lambat.

MEF, LinFu dan Spring.NET lebih cepat dari Ninject, tetapi masih sangat lambat. AutoFac, Catel dan Windsor datang berikutnya, diikuti oleh StructureMap, Unity dan LightCore. Kerugian dari Spring.NET adalah, itu hanya dapat dikonfigurasi dengan XML.

SimpleInjector, Hiro, Funq, Munq dan Dynamo menawarkan kinerja terbaik, mereka sangat cepat. Cobalah mereka!

Terutama Injector Sederhana sepertinya menjadi pilihan yang baik. Ini sangat cepat, memiliki dokumentasi yang baik dan juga mendukung skenario canggih seperti intersepsi dan dekorator generik.

Anda juga dapat mencoba menggunakan Perpustakaan Pemilih Layanan Umum dan mudah-mudahan mencoba beberapa opsi dan melihat mana yang terbaik untuk Anda.

Beberapa informasi tentang Perpustakaan Pemilih Layanan Umum dari situs:

Perpustakaan menyediakan abstraksi atas wadah IoC dan pencari layanan. Menggunakan perpustakaan memungkinkan aplikasi untuk mengakses kemampuan secara tidak langsung tanpa bergantung pada referensi keras. Harapannya adalah bahwa dengan menggunakan perpustakaan ini, aplikasi dan kerangka kerja pihak ketiga dapat mulai memanfaatkan IoC / Lokasi Layanan tanpa mengikat diri mereka pada implementasi tertentu.

Memperbarui

13.09.2011: Funq dan Munq ditambahkan ke daftar kontestan. Grafik juga diperbarui, dan Spring.NET dihapus karena kinerjanya yang buruk.

04.11.2011: "tambah Simple Injector , kinerjanya yang terbaik dari semua kontestan".

Pranav Shah
sumber
(Dari mengikuti Link perbandingan) Diperbarui baru-baru ini, menarik untuk melihat perbedaan kecepatan (ditambah matriks fitur dasar). Terima kasih.
lko
Perbandingan itu tidak begitu dapat diandalkan karena sejauh yang saya tahu Ninject memiliki ekstensi untuk konfigurasi Intersepsi dan XML, sedangkan perbandingan menyatakan tidak.
Daniel
15
ini adalah perbandingan yang sangat kuantitatif. bagaimana dengan fitur non-kinerja seperti ukuran file atau jumlah dependensi yang diperlukan? Selain itu, tindakan subjektif seperti kualitas dokumentasi atau kegunaan akan sangat membantu. Maksud saya adalah bahwa ada faktor yang perlu dipertimbangkan selain kecepatan.
FistOfFury
1
Seperti Jeremy Miller, penulis dari StructureMap mengatakan di masa lalu ... parafrase - Yang pasti ada wadah IOC lebih cepat, tetapi mereka tidak memiliki set fitur lengkap.
Tom Stickel
lihat ini: iocservicestack.net
Rajesh Jinaga
49

Baca saja blog pembanding kontainer .Net DI yang hebat ini oleh Philip Mat.

Dia melakukan beberapa tes perbandingan kinerja menyeluruh pada;

Dia merekomendasikan Autofac karena kecil, cepat, dan mudah digunakan ... Saya setuju. Tampaknya Unity dan Ninject adalah yang paling lambat dalam pengujiannya.

Brodie
sumber
5
Ada pembaruan untuk posting .Net DI Container Speed ​​Redux : Pada dasarnya, ada pendekatan yang salah yang diambil untuk Unity di tempat pertama. Dengan pengukuran baru, Unity terlihat jauh lebih baik.
Volker von Einem
33

Penafian: Pada awal 2015, ada banyak perbandingan fitur IoC Container dari Jimmy Bogard , berikut ringkasannya:

Kontainer yang Dibandingkan:

  • Autofac
  • Tidak ada
  • Injector sederhana
  • StructureMap
  • Kesatuan
  • Windsor

Skenarionya adalah ini: Saya memiliki antarmuka, IMediator, di mana saya dapat mengirim satu permintaan / tanggapan atau pemberitahuan ke beberapa penerima:

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; 
}

Saya kemudian membuat satu set permintaan / tanggapan / pemberitahuan:

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 { }

Saya tertarik melihat beberapa hal sehubungan dengan dukungan wadah untuk obat generik:

  • Setup untuk obat generik terbuka (mendaftar IRequestHandler <,> dengan mudah)
  • Pengaturan untuk beberapa registrasi obat generik terbuka (dua atau lebih Penangan Identifikasi)

Pengaturan untuk varian umum (mendaftarkan penangan untuk basisInotifikasi / membuat pipa permintaan) Penangan saya cukup mudah, mereka hanya menampilkan konsol:

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();
  • Open generics: ya, secara implisit
  • Beberapa obat generik terbuka: ya, secara implisit
  • Kontravarian umum: ya, secara eksplisit

Tidak ada

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);
  • Open generics: ya, secara implisit
  • Beberapa obat generik terbuka: ya, secara implisit
  • Kontravarian umum: ya, dengan ekstensi buatan pengguna

Injector sederhana

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);
  • Open generics: ya, secara eksplisit
  • Beberapa obat generik terbuka: ya, secara eksplisit
  • Kontravarian umum: ya, secara implisit (dengan pembaruan 3.0)

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<>));
    });
});
  • Open generics: ya, secara eksplisit
  • Beberapa obat generik terbuka: ya, secara eksplisit
  • Kontravarian umum: ya, secara implisit

Kesatuan

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;
}
  • Open generics: ya, secara implisit
  • Beberapa obat generik terbuka: ya, dengan ekstensi buatan pengguna
  • Contravariance umum: 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());
  • Open generics: ya, secara implisit
  • Beberapa obat generik terbuka: ya, secara implisit
  • Kontravarian umum: ya, dengan ekstensi buatan pengguna
stratovarius
sumber
Luar biasa! Btw, ringkasan di atas tidak mengenai Windsor, tetapi tersedia di artikel asli Jimmy.
Louis
Wow tidak ada yang memperingatkan tentang hal itu sebelumnya (: Saya menambahkan windsor, terima kasih @Louis
stratovarius
21

Sebenarnya ada banyak kerangka kerja IoC. Sepertinya setiap programmer mencoba menulis satu di beberapa titik karir mereka. Mungkin bukan untuk menerbitkannya, tetapi untuk mempelajari cara kerja batin.

Saya pribadi lebih suka autofac karena cukup fleksibel dan memiliki sintaksis yang cocok untuk saya (walaupun saya sangat benci bahwa semua metode register adalah metode ekstensi).

Beberapa kerangka kerja lain:

jgauffin
sumber
Hai @abatishchev! :) ... ide awalnya adalah untuk memastikan metode pihak ketiga dan built-in berada pada pijakan yang sama; banyak metode "register" harus dikirimkan secara terpisah (misalnya RegisterControllers()untuk MVC) jadi saya pikir merancang sekitar kasus itu bermanfaat. (Ini dirancang 5+ tahun yang lalu.)
Nicholas Blumhardt
1
@NicholasBlumhardt: Hai! :) Maaf atas keterlambatan respons, notifikasi hilang di antara yang lain. Sebenarnya demi konsistensi seperti itu masuk akal bagi saya. Bagaimana menurut Anda sekarang, bagaimana Anda mendesainnya?
abatishchev
@abatishchev Saya tidak setuju dengan jgauffin. Metode ekstensi tidak tertutup untuk ekstensi, mereka ekstensi. Anda menulis inti dari kerangka kerja Anda yang dapat melakukan semua yang seharusnya dan dengan metode ekstensi Anda memberikan beberapa fungsi tambahan, mungkin beberapa pembantu default tetapi orang lain bebas untuk menulis ekstensi mereka sendiri. Saya akan mengatakan jika kerangka kerja Anda menerima metode ekstensi untuk memperpanjangnya maka itu kerangka kerja yang baik.
t3chb0t
6

Nah, setelah melihat-lihat perbandingan terbaik yang saya temukan sejauh ini adalah:

Itu adalah jajak pendapat yang diambil pada Maret 2010.

Satu hal yang menarik bagi saya adalah bahwa orang-orang yang telah menggunakan Kerangka DI / IoC dan suka / tidak suka, StructureMap tampaknya keluar di atas.

Juga dari jajak pendapat, tampaknya Castle.Windsor dan StructureMap tampaknya paling disukai.

Menariknya, Unity dan Spring.Net tampaknya menjadi pilihan populer yang paling tidak disukai. (Saya sedang mempertimbangkan Unity karena malas (dan lencana / dukungan Microsoft), tetapi saya akan melihat lebih dekat pada Castle Windsor dan StructureMap sekarang.)

Tentu saja ini mungkin (?) Tidak berlaku untuk Unity 2.0 yang dirilis pada Mei 2010.

Semoga orang lain bisa memberikan perbandingan berdasarkan pengalaman langsung.

ocodo
sumber
2
Persatuan itu cukup bagus. Ini mencakup sebagian besar yang dibutuhkan seseorang, meskipun beberapa orang mengeluh tentang hal itu tidak menyelesaikan dependensi melingkar. Aku menyukainya. Saya melakukan semua yang saya butuhkan.
Dmitri Nesteruk
Banyak pengembang menggunakan Castle.Windsor bahkan tanpa menyadarinya. Ini adalah Ioc default untuk NHibernate . (Setidaknya dengan FluentNHibernate saya downloded kemarin). Saya juga melihat implementasi NHibernate yang menggunakan LinFu nstead
k3b
5

Lihat perbandingan net-ioc-frameworks pada kode google termasuk linfu dan spring.net yang tidak ada dalam daftar Anda saat saya menulis teks ini.

Saya bekerja dengan spring.net: Ini memiliki banyak fitur (aop, libraries, docu, ...) dan ada banyak pengalaman dengannya di dotnet dan java-world. Fitur-fiturnya dimodulasi sehingga Anda tidak harus mengambil semua fitur. Fitur-fiturnya adalah abstraksi dari masalah umum seperti databaseabstraction, loggingabstraction. namun sulit untuk melakukan dan men-debug konfigurasi-IOC.

Dari apa yang saya baca sejauh ini: Jika saya harus memilih untuk proyek kecil atau menengah, saya akan menggunakan ninject sejak ioc-konfigurasi dilakukan dan debuggable di c #. Tapi aku belum bekerja dengannya. untuk sistem modular besar saya akan tetap dengan spring.net karena perpustakaan-abstraksi.

k3b
sumber