Làm thế nào để các khung C # DI / IoC chính so sánh? [đóng cửa]


308

Có nguy cơ bước vào lãnh thổ chiến tranh thần thánh, điểm mạnh và điểm yếu của các khung DI / IoC phổ biến này là gì và có thể dễ dàng được coi là tốt nhất? ..:

  • Ninject
  • Đoàn kết
  • Castle.Windsor
  • Tự động điền
  • Sơ đồ cấu trúc

Có bất kỳ Khung DI / IoC nào khác cho C # mà tôi chưa liệt kê ở đây không?

Trong trường hợp sử dụng của tôi, tôi đang xây dựng một ứng dụng WPF của khách hàng và cơ sở hạ tầng dịch vụ WCF / SQL, dễ sử dụng (đặc biệt là về cú pháp rõ ràng và súc tích), tài liệu nhất quán, hỗ trợ cộng đồng tốt và hiệu suất là tất cả các yếu tố quan trọng trong sự lựa chọn của tôi

Cập nhật:

Các tài nguyên và các câu hỏi trùng lặp được trích dẫn dường như đã lỗi thời, liệu ai đó có kiến ​​thức về tất cả các khung này có thể đưa ra và cung cấp một số hiểu biết thực sự?

Tôi nhận ra rằng hầu hết ý kiến ​​về chủ đề này có thể bị sai lệch, nhưng tôi hy vọng rằng ai đó đã dành thời gian để nghiên cứu tất cả các khung này và có ít nhất một so sánh chung khách quan.

Tôi khá sẵn lòng thực hiện các cuộc điều tra của riêng mình nếu điều này chưa được thực hiện trước đây, nhưng tôi cho rằng đây là điều mà ít nhất một vài người đã làm.

Cập nhật lần thứ hai:

Nếu bạn có kinh nghiệm với nhiều hơn một container DI / IoC, vui lòng xếp hạng và tóm tắt những ưu và nhược điểm của chúng, cảm ơn bạn. Đây không phải là một bài tập trong việc khám phá tất cả các thùng chứa nhỏ mà mọi người đã tạo ra, tôi đang tìm kiếm sự so sánh giữa các khung phổ biến (và hoạt động).


1
Câu hỏi tương tự như [Ninject vs Unity for DI] ( stackoverflow.com/questions/1054801/ninject-vs-unity-for-di ), nhưng có lẽ đã đến lúc theo dõi.
Matthew Flaschen

2
bản sao có thể có của [So sánh Castle Windsor, Unity và StructMap] ( stackoverflow.com/questions/2216684/iêu )
Mauricio Scheffer

@slomojo: Có thể trùng lặp. stackoverflow.com/questions/4509458/ioc-comparutions-closes . Ngoài ra còn có liên kết cho thấy mức độ phổ biến của IoC trong câu trả lời. Có một cái nhìn vào nó.
dhinesh

@chibacity - Tôi đã sử dụng nó trên ... 4 dự án, hai dự án đầu tiên thực sự cơ bản, không có vấn đề gì, hai dự án thứ hai, Unity gây ra cho chúng tôi rất nhiều vấn đề khi nói đến việc xây dựng, khả năng bảo trì, khả năng đọc. Cuối cùng, chúng tôi đã tách Unity ra khỏi cả hai và thay thế nó bằng StructMap, việc xây dựng trình xây dựng rất đơn giản, cấu hình sạch sẽ và có thể bảo trì. Trong thời gian cá nhân của tôi, tôi đã chơi với AutoFac, nhưng tôi thấy khó hiểu, đã xem một số tài liệu để hiểu rõ hơn về nó. Phần còn lại tôi chỉ có thể nhận xét về những gì tôi đã đọc.
Phill

Một vấn đề chúng tôi gặp phải là với SSRS, nó đã âm thầm thất bại và bước qua mã chúng tôi không thể hiểu tại sao nó lại thất bại, ngoại lệ là mơ hồ. Chúng tôi đã dành một tuần để viết các tác phẩm để làm cho nó hoạt động. Cuối cùng, khi chúng tôi chuyển sang StructMap, chúng tôi đã có một nỗ lực khác và trong vài phút sử dụng 'ObjectFactory.WhatDoIHave ()', chúng tôi đã biết rằng IoC đang được xây dựng trước khi các hội đồng được tải vào AppDomain, vì vậy các giao diện không bao giờ được đăng ký với bê tông các loại.
Phill

Câu trả lời:


225

Mặc dù câu trả lời toàn diện cho câu hỏi này chiếm hàng trăm trang sách của tôi , đây là biểu đồ so sánh nhanh mà tôi vẫn đang làm việc:

Một bảng giải thích sự khác biệt giữa một số DIC


40
Tôi đã đọc MEAP của cuốn sách của bạn và đã tự hỏi tại sao bạn lại bỏ Ninject ra khỏi nó?
Martin Owen

2
Câu trả lời một phần có thể được tìm thấy ở đây: manning-sandbox.com/thread.jspa?threadID=38943
Mark Seemann

25
@Mark, cảm ơn vì điều này, hy vọng câu trả lời của bạn có thể bao gồm Ninject (quan trọng, không chỉ vì sự cường điệu mới xung quanh nó, mà còn do nó sử dụng các tính năng ngôn ngữ mới.)
ocodo

3
Ninject trong khi tương tự như AutoFac có nhiều cách, nó được Nhóm NUGET sử dụng và bộ chứa IOC được tải xuống phổ biến nhất. Tôi đã thất vọng vì nó không có trong cuốn sách Dependency Injection của .NET. Nếu có một phiên bản thứ 2 theo cách nhìn của ngành công nghiệp, hy vọng nó sẽ đưa nó vào cuốn sách. Tôi tình cờ gặp Unity, MEF (không phải DI thực sự), Ninject hoặc StructurMap, tôi chỉ đơn giản là chưa đạt được hợp đồng hoặc hợp đồng biểu diễn từ xa sử dụng spring.net hoặc autofac, v.v ...
Tom Stickel

2
Unity 3.5 đã hỗ trợ đăng ký dựa trên quy ước: nuget.org/packages/Unity/3.5.1404 . Xóa một nhược điểm ;-)
Vladimir Dorokhov

116

Tôi đã xem qua một so sánh hiệu suất khác (cập nhật mới nhất ngày 10 tháng 4 năm 2014). Nó so sánh như sau:

Dưới đây là một bản tóm tắt nhanh chóng từ bài viết:

Phần kết luận

Ninject chắc chắn là container chậm nhất.

MEF, LinFu và Spring.NET nhanh hơn Ninject, nhưng vẫn khá chậm. AutoFac, Catel và Windsor tiếp theo, tiếp theo là StructMap, Unity và LightCore. Một nhược điểm của Spring.NET là, chỉ có thể được cấu hình bằng XML.

SimpleInjection, Hiro, Funq, Munq và Dynamo cung cấp hiệu suất tốt nhất, chúng cực kỳ nhanh. Hãy thử cho họ!

Đặc biệt là In phun đơn giản dường như là một lựa chọn tốt. Nó rất nhanh, có một tài liệu tốt và cũng hỗ trợ các kịch bản nâng cao như đánh chặn và trang trí chung.

Bạn cũng có thể thử sử dụng Thư viện chọn dịch vụ chung và hy vọng thử nhiều tùy chọn và xem cái nào phù hợp nhất với bạn.

Một số thông tin về Thư viện chọn dịch vụ chung từ trang web:

Thư viện cung cấp một bản tóm tắt về các bộ chứa IoC và bộ định vị dịch vụ. Sử dụng thư viện cho phép một ứng dụng truy cập gián tiếp các khả năng mà không cần dựa vào các tài liệu tham khảo cứng. Hy vọng là sử dụng thư viện này, các ứng dụng và khung của bên thứ ba có thể bắt đầu tận dụng Vị trí dịch vụ / IoC mà không cần phải thực hiện một triển khai cụ thể.

Cập nhật

Ngày 13 tháng 9 năm 2011: FunqMunq đã được thêm vào danh sách thí sinh. Các biểu đồ cũng được cập nhật và Spring.NET đã bị xóa do hiệu suất kém.

04.11.2011: "Thêm In phun đơn giản , màn trình diễn là tốt nhất trong tất cả các thí sinh".


(Từ theo liên kết so sánh) Được cập nhật gần đây, thật thú vị khi thấy sự khác biệt về tốc độ (cộng với ma trận các tính năng cơ bản). Cảm ơn.
lko

Sự so sánh đó không đáng tin cậy lắm vì theo như tôi biết Ninject có các phần mở rộng cho cả cấu hình Đánh chặn và cấu hình XML, trong khi so sánh thì không.
Daniel

15
đây là một so sánh rất định lượng Điều gì về các tính năng không hiệu suất như kích thước tệp hoặc số lượng phụ thuộc cần thiết? Ngoài ra, các biện pháp chủ quan như chất lượng tài liệu hoặc khả năng sử dụng sẽ hữu ích. Quan điểm của tôi là có những yếu tố để xem xét khác hơn là tốc độ.
FistOfFury

1
Giống như Jeremy Miller, tác giả của StructMap đã nói trước đây ... diễn giải - Điều đó chắc chắn rằng có các thùng chứa IOC nhanh hơn, nhưng chúng thiếu một bộ tính năng đầy đủ.
Tom Stickel

kiểm tra cái này: iocservicestack.net
Rajesh Jinaga

49

Chỉ cần đọc blog so sánh container .Net DI tuyệt vời này của Philip Mat.

Ông làm một số bài kiểm tra so sánh hiệu suất kỹ lưỡng trên;

Ông khuyên dùng Autofac vì nó nhỏ, nhanh và dễ sử dụng ... Tôi đồng ý. Có vẻ như UnityNinject là chậm nhất trong các thử nghiệm của anh ấy.


5
Có một bản cập nhật cho bài đăng .Net DI Container Redux Redux : Ở dòng dưới cùng, đã có một cách tiếp cận sai đối với Unity ở vị trí đầu tiên. Với các phép đo mới, Unity trông đẹp hơn nhiều.
Volker von Einem

33

Tuyên bố miễn trừ trách nhiệm: Tính đến đầu năm 2015, có một so sánh tuyệt vời về các tính năng của IoC Container từ Jimmy Bogard , đây là một bản tóm tắt:

So sánh container:

  • Tự động điền
  • Ninject
  • Vòi phun đơn giản
  • Sơ đồ cấu trúc
  • Đoàn kết
  • Lâu đài

Kịch bản là thế này: Tôi có một giao diện, IMedoder, trong đó tôi có thể gửi một yêu cầu / phản hồi hoặc một thông báo cho nhiều người nhận:

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

Sau đó tôi đã tạo một bộ cơ sở các yêu cầu / phản hồi / thông báo:

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

Tôi đã quan tâm đến việc xem xét một vài điều liên quan đến hỗ trợ container cho thuốc generic:

  • Thiết lập cho generic generic (dễ dàng đăng ký IRequestHandler <,>)
  • Thiết lập cho nhiều đăng ký của generic generic (hai hoặc nhiều INotificationHandlers)

Thiết lập cho phương sai chung (đăng ký trình xử lý cho cơ sở INotification / tạo đường ống yêu cầu) Trình xử lý của tôi khá đơn giản, chúng chỉ xuất ra giao diện điều khiển:

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 */ }

Tự động điền

var builder = new ContainerBuilder();
builder.RegisterSource(new ContravariantRegistrationSource());
builder.RegisterAssemblyTypes(typeof (IMediator).Assembly).AsImplementedInterfaces();
builder.RegisterAssemblyTypes(typeof (Ping).Assembly).AsImplementedInterfaces();
  • Tổng quát mở: có, ngầm
  • Nhiều khái quát mở: có, ngầm
  • Chống chỉ định chung: có, rõ ràng

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);
  • Tổng quát mở: có, ngầm
  • Nhiều khái quát mở: có, ngầm
  • Chống chỉ định chung: có, với các tiện ích mở rộng do người dùng tạo

Vòi phun đơn giản

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);
  • Tổng quát mở: có, rõ ràng
  • Nhiều khái quát mở: có, rõ ràng
  • Chống chỉ định chung: có, ngầm (với bản cập nhật 3.0)

Sơ đồ cấu trúc

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<>));
    });
});
  • Tổng quát mở: có, rõ ràng
  • Nhiều khái quát mở: có, rõ ràng
  • Chống chỉ định chung: có, ngầm

Đoàn kết

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;
}
  • Tổng quát mở: có, ngầm
  • Nhiều tổng quát mở: có, với tiện ích mở rộng do người dùng tạo
  • Chống chỉ định chung: derp

Lâu đài

var container = new WindsorContainer();
container.Register(Classes.FromAssemblyContaining<IMediator>().Pick().WithServiceAllInterfaces());
container.Register(Classes.FromAssemblyContaining<Ping>().Pick().WithServiceAllInterfaces());
container.Kernel.AddHandlersFilter(new ContravariantFilter());
  • Tổng quát mở: có, ngầm
  • Nhiều khái quát mở: có, ngầm
  • Chống chỉ định chung: có, với tiện ích mở rộng do người dùng tạo

Thông minh! Btw, bản tóm tắt ở trên đã bỏ qua Windsor, nhưng nó có sẵn trong bài viết gốc của Jimmy.
Louis

Wow không ai cảnh báo về điều đó trước đây (: Tôi đã thêm gió, cảm ơn @Louis
stratovarius

21

Trên thực tế có hàng tấn khung IoC. Có vẻ như mọi lập trình viên đều cố gắng viết một bài nào đó trong sự nghiệp của họ. Có lẽ không phải để xuất bản nó, nhưng để tìm hiểu các hoạt động bên trong.

Cá nhân tôi thích autofac vì nó khá linh hoạt và có cú pháp phù hợp với tôi (mặc dù tôi thực sự ghét rằng tất cả các phương thức đăng ký là phương thức mở rộng).

Một số khung khác:


Xin chào @abatishchev! :) ... ý tưởng ban đầu là đảm bảo các phương thức tích hợp và bên thứ ba của cùng một bên; nhiều phương thức "đăng ký" phải được gửi riêng (ví dụ RegisterControllers()cho MVC) vì vậy tôi nghĩ rằng thiết kế xung quanh trường hợp đó là đáng giá. (Điều này đã được thiết kế hơn 5 năm trước.)
Nicholas Blumhardt

1
@NicholasBlumhardt: Xin chào! :) Xin lỗi vì phản hồi muộn, thông báo đã bị mất giữa những người khác. Trên thực tế vì lợi ích của sự nhất quán có ý nghĩa với tôi. Làm thế nào để bạn nghĩ bây giờ, làm thế nào bạn sẽ thiết kế nó?
abatishchev

@abatishchev Tôi không đồng ý với jgauffin. Các phương thức mở rộng không được đóng để mở rộng, chúng là phần mở rộng. Bạn viết cốt lõi của khung công tác có thể làm tất cả những gì cần thiết và với các phương thức mở rộng, bạn cung cấp một số chức năng bổ sung, có thể một số trình trợ giúp mặc định nhưng bất kỳ ai khác có thể tự do viết các tiện ích mở rộng của riêng họ. Tôi sẽ nói nếu khung của bạn chấp nhận các phương thức mở rộng để mở rộng thì đó là một khung tốt.
t3chb0t

6

Chà, sau khi xem xét sự so sánh tốt nhất mà tôi tìm thấy cho đến nay là:

Đó là một cuộc thăm dò được thực hiện vào tháng 3 năm 2010.

Một điểm thú vị đối với tôi là những người đã sử dụng Khung DI / IoC và thích / không thích nó, StructMap dường như xuất hiện trên đầu trang.

Cũng từ những cuộc thăm dò, có vẻ như Castle.WindsorStructureMap dường như được ưa chuộng cao nhất.

Thật thú vị, UnitySpring.Net dường như là những lựa chọn phổ biến thường không thích nhất. (Tôi đã xem xét Unity vì sự lười biếng (và huy hiệu / hỗ trợ của Microsoft), nhưng bây giờ tôi sẽ xem xét kỹ hơn về Castle Windsor và StructMap.)

Tất nhiên, điều này có lẽ (?) Không áp dụng cho Unity 2.0, được phát hành vào tháng 5 năm 2010.

Hy vọng rằng người khác có thể cung cấp một so sánh dựa trên kinh nghiệm trực tiếp.


2
Đoàn kết là khá tốt. Nó bao gồm hầu hết những gì người ta cần, mặc dù một số người phàn nàn về việc nó không giải quyết được sự phụ thuộc theo vòng tròn. Tôi thích nó. Tôi làm mọi thứ tôi cần.
Dmitri Nesteruk

Nhiều nhà phát triển đang sử dụng Castle.Windsor mà không hề biết. Đó là Ioc mặc định cho NHibernate . (Ít nhất là với FluentNHibernate i đã bị hủy ngày hôm qua). Tôi cũng thấy một triển khai NHibernate sử dụng LinFu nstead
k3b

5

Xem để so sánh các net-ioc-framework trên mã google bao gồm linfu và spring.net không có trong danh sách của bạn trong khi tôi viết văn bản này.

Tôi đã làm việc với spring.net: Nó có nhiều tính năng (aop, thư viện, docu, ...) và có rất nhiều kinh nghiệm với nó trong dotnet và thế giới java. Các tính năng được mô đun hóa để bạn không phải mất tất cả các tính năng. Các tính năng là trừu tượng của các vấn đề phổ biến như cơ sở dữ liệu, cơ sở dữ liệu. tuy nhiên, nó là khác nhau để làm và gỡ lỗi cấu hình IoC.

Từ những gì tôi đã đọc cho đến nay: Nếu tôi phải chọn một dự án nhỏ hoặc vừa, tôi sẽ sử dụng ninject vì cấu hình ioc được thực hiện và có thể gỡ lỗi trong c #. Nhưng tôi chưa làm việc với nó. đối với hệ thống mô-đun lớn, tôi sẽ ở lại với spring.net vì các thư viện trừu tượng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.