2010-09-28 28 views
6

Tôi đã đọc về các khung điều khiển Inversion của Kiểm soát và tôi chỉ đang chơi xung quanh với câu hỏi: "Tại sao tôi lại cần một khung làm việc này?"Tại sao sử dụng khung công tác IoC

Đừng hiểu lầm câu hỏi của tôi ... mẫu là thứ mà chúng tôi lập trình sử dụng thường xuyên nhưng ... một khuôn khổ đầy đủ tính năng để làm điều đó?

Tôi phải thiếu điều gì đó và đó là lý do tôi đăng câu hỏi. Tôi đã nhìn thấy rất nhiều ví dụ trên web và tôi không hiểu. mi tâm bị chặn ý tưởng có thể.

Chỉ cần có một cái nhìn vào ví dụ trang của Ninject Trang chủ:

public class Samurai { 
    public IWeapon Weapon { get; private set; } 
    public Samurai(IWeapon weapon) { 
     Weapon = weapon; 
    } 
} 

public class WarriorModule : NinjectModule { 
    public override void Load() { 
     Bind<IWeapon>.To<Sword>(); 
    } 
} 

Lớp "Samurai" là ok với tôi. Khung "NinjectModule" có vẻ không cần thiết đối với tôi.

tôi giả sử sau này trong mã chúng tôi sẽ tạo mới "Samurai" trường hợp đi qua trong những trường hợp "Thanh kiếm" với nó, một cái gì đó như:

Samurai theWarrior = new Samurai(WarriorModule.GetInstance(IWeapon));//no coupling 

mà có thể được thay thế bằng:

Samurai theWarrior = new Samurai(new Sword());//still no coupling 

hoặc

Samurai theWarrior = new Samurai(GetWeaponFromXML());//no coupling yet 

của phần tôi đang thiếu gì? Bạn có thể vui lòng nói về một số kịch bản mà Ioc khuôn khổ có thể cần thiết trong ứng dụng của tôi?

Cảm ơn.

CẬP NHẬT SAU 4 TRẢ LỜI: Tôi thực sự thích tất cả các câu trả lời tôi nhận được từ các bạn. Tôi chỉ đọc bài này dependency-injection-dissection/ nơi anh chàng sử dụng nó cho Unit Testing và liên kết StackOverflow mà bạn vừa cung cấp và Yeah, tôi đã bỏ lỡ phần phức tạp lớn lớn, vì vậy hãy tùy chỉnh bản thân mình để sử dụng một khung công tác IoC. Cảm ơn một lần nữa.

Tôi sẽ bỏ phiếu cho câu trả lời của bạn nhưng tôi chỉ nhận được thông báo màu cam nói rằng tôi không thể.

Nhờ người đã đánh dấu mã tôi đã đăng.

+1

tôi sẽ đề nghị chỉnh sửa câu hỏi của bạn để làm cho khối mã khối mã thực tế, bởi một trong hai 'làm nổi bật và nhấn Ctrl-k 'hoặc bằng cách chèn bốn dấu cách trước mỗi dòng mã. – jcolebrand

+0

'new Samurai (new Sword()); // vẫn không có coupling' Có một khớp nối chặt chẽ ở đây, bạn sử dụng' new'. Khi bạn refactor rằng, bạn sẽ phải thay đổi mọi nơi mà instantiates một Sword. – nos

+0

bản sao có thể có của [Tại sao tôi cần một thùng chứa IoC thay vì mã DI đơn giản?] (Http://stackoverflow.com/questions/871405/why-do-i-need-an-ioc-container-as-opposed -to-straightforward-di-code) –

Trả lời

4

dụ của bạn là khá thẳng về phía trước có chỉ có hai lớp, nhưng khi bạn có một ví dụ thực tế đời sống nó sớm bị lộn xộn:

var form = new OrderEntryForm(
    new OrderService(
     new OrderReposity(
      new DatabaseGateway(
       new DataProviderFactory())))) 

Một IoC container có thể làm tất cả những hệ thống dây điện lên cho bạn, làm cho bạn cuộc sống dễ dàng hơn nhiều.

Đây là một ví dụ từ một câu hỏi tương tự, mà đi vào tất cả các chi tiết: https://stackoverflow.com/questions/45191/ioc-explain-and-more-important-when-to-use-it/45197#45197

+0

Hộp chứa IoC làm giảm độ phức tạp như thế nào? Tôi có nghĩa là bạn vẫn sẽ phải xác định toàn bộ cây nhưng phải sử dụng một ngôn ngữ khác dễ bị lỗi hơn. –

6

Đây là vấn đề với mẫu mã. Họ là một trong hai phức tạp và bạn đã không giải thích quan điểm của bạn, hoặc họ tầm thường và sau đó có vẻ vô nghĩa.

Những gì WarriorModule đang làm là ràng buộc một loại cụ thể vào một giao diện, và vì vậy bất cứ khi nào một lớp khác cần thực hiện giao diện đó, nó sẽ tự động nhận được một container IoC. Lớp với sự phụ thuộc không phụ thuộc vào loại bê tông, và do đó có sự ghép nối thấp hơn và khả năng kiểm tra cao hơn. Tôi nghĩ bạn đã biết điều đó rồi.

Trong trường hợp thay thế, lớp Samurai không được kết hợp với lớp kiếm, nhưng mã gọi vẫn còn. Bạn có thể đẩy nó ra một cấp độ khác, nhưng mã đó bây giờ sẽ có sự phụ thuộc, và lớp học can thiệp của bạn bây giờ sẽ phải sắp xếp tất cả các phụ thuộc.

Vùng chứa IoC thực hiện điều này cho tất cả các ánh xạ, đặt nó chỉ ở một vài nơi (các lớp mô-đun). Phần còn lại của mã của bạn là miễn phí không phải để chăm sóc, không có phụ thuộc vào các loại cụ thể.

Hy vọng điều đó sẽ hữu ích.

+0

Thích nhận xét này; "Đây là vấn đề với các mẫu mã. Chúng phức tạp và bạn đã không giải thích được quan điểm của bạn, hoặc chúng tầm thường và sau đó có vẻ vô nghĩa." Tôi thường nói nhiều hơn về cái sau. Đặc biệt với Ninject, không có ví dụ nào được đưa ra biện minh cho việc sử dụng của nó bởi vì chúng quá đơn giản và không thể hiện bất kỳ chi tiết nào làm cho nó đáng giá ở trên và ngoài DI thủ công. –

+0

Nếu bạn có một thiết kế tốt, bạn không có nhiều khớp nối. Và đâu là diffrence nếu tôi xác định hệ thống dây điện với XML hoặc mã ở một nơi? –

1

Gần đây, tôi đã bắt đầu sử dụng Unity cho IoC và không nghi ngờ gì làm cho cuộc sống của tôi dễ dàng hơn.

Tôi sẽ chỉ dán nguyên văn mã của mình và hy vọng bạn thấy nó hữu ích. Ai đó có kinh nghiệm hơn có thể cung cấp cho bạn nhiều hơn.

Ngoài ra, tôi thấy hữu ích khi đọc bài báo về DI của Fowler.

static class Program 
{ 
    [STAThread] 
    static void Main() 
    { 
     Application.EnableVisualStyles(); 
     Application.SetCompatibleTextRenderingDefault(false); 

     using (IUnityContainer container = new UnityContainer()) 
     { 
      container 

       .RegisterType<ILogger, StatSyncherFormView>(new myLife()) 

       // GUI 
       .RegisterType<IStatSyncherView, StatSyncherFormView>() 

       // Services 
       .RegisterType<ISalesForceWebServices, SalesForceWebServices1>() 

       .RegisterInstance(new SalesForceWebServices1(
        "XXX", "XXX", 
        "https://login.salesforce.com/services/Soap/c/19.0/0DF70000000CfHq", 
        "https://na5-api.salesforce.com/services/Soap/s/19.0")) 


       .RegisterType<ISalesForceService, SalesForceService1>() 

       .RegisterType<IRestApiCall, RestApiCall1>() 

       .RegisterType<IDirectTrackService, DirectTrackService1>() 

       .RegisterType<IDAgentsService, DAgentsService1>() 

       .RegisterType<IQuickBooksService, QuickBooksService1>(); 

      StatSyncherPresenter p = container.Resolve<StatSyncherPresenter>(); 

      Application.Run((Form)p.view); 
     } 
    } 

Một trong những điều tôi thấy hữu ích nhất là:

public class AnyClassCreatedByContainer 
{ 
    [Dependency] 
    public ILogger Logger { get; set; } 
} 
1

Mặc dù Samurai theWarrior = new Samurai(new Sword()); vẫn không có khớp nối, nếu bạn muốn cung cấp cho tất cả các samurai trong ứng dụng của bạn một <insert favourite weapon here>, bạn sẽ phải thay đổi tất cả các mã gọi của bạn để thay đổi vũ khí mới, trong khi với IoC bạn sẽ thay đổi nó ở một chỗ và tất cả các samura của bạn sẽ sử dụng vũ khí mới.

Các vấn đề liên quan