2012-05-30 14 views
6

Trong ứng dụng Prism của tôi, container MEF có sẵn trong lớp Bootstrapper thông qua thuộc tính Container.Tại sao MEF-container không có sẵn trong mô-đun?

Nhưng không phải từ mô-đun lớp (IModule). Tôi chỉ có thể nhập vùng chứa thông qua IServiceLocator.

Tại sao? Tôi nghĩ rằng nó có ý nghĩa để sử dụng một giao diện chung chống lại công nghệ bê tông, nhưng hướng dẫn Prism 4.1 yêu cầu chúng tôi không sử dụng IServiceLocator (trong Considerations for Using IServiceLocator).

Trả lời

6

Tôi nghĩ rằng nó tương ứng với Prism hoặc MEF, nhưng với nguyên tắc Dependency Injection và các phương pháp hay nhất nói chung. (Yeah, tôi hôn rằng MEF không phải là DI container, nhưng ở đây nó được sử dụng gần như là DI container, vì vậy tôi giả sử sử dụng các thực hành tương tự ở đây).

Trong thực hành tốt nhất của DI (this cuốn sách là rất mát mẻ, tôi khuyên bạn nên nó) rất tốt để có các bước như vậy trong DI "công việc":

  • đăng ký tất cả các loại cần thiết (trong Prism - bởi Bootstrapper. ConfigureCatalog() phương pháp)
  • đối tượng quyết tâm gốc (với tất cả các đối tượng lồng nhau Trong Prism -. bởi Bootstrapper.CreateShell() phương pháp)
  • sử dụng đối tượng gốc của bạn
  • phát hành bạn đối tượng gốc

Lý tưởng nhất, bạn KHÔNG nên sử dụng DI container nữa. Mã của bạn KHÔNG nên biết về sự tồn tại của DI container (từ bên này Unity thực sự là DI container, bởi vì bạn có thể viết mã mà sẽ không biết về việc sử dụng DI container). Nếu mã của bạn biết về nó - nó PHỤC VỤ trên DI container, và đó là điều xấu.

PS.Nếu bạn muốn sử dụng thùng chứa MEF trong mô-đun của bạn anyway (ví dụ, bởi vì bạn không phải là rất quen thuộc với DI mô hình hoặc bạn có một số nhiệm vụ rất cụ thể), bạn có thể thử một cái gì đó như:

[ModuleExport(typeof(YourModule))] 
public class YourModule : IModule 
{ 
    public static CompositionContainer CompositionContainer; 

    [ImportingConstructor] 
    public void YourModule(CompositionContainer container) 
    { 
     this.CompositionContainer = container; 
    } 
} 

Đừng quên đăng ký hộp chứa MEF của bạn trong Boostrapper của bạn:

public class YourBootstrapper: MefBootstrapper 
{ 
    protected override CompositionContainer CreateContainer() 
    { 
     var container = base.CreateContainer(); 
     container.ComposeExportedValue(container); 
     return container; 
    } 
} 
+1

trong khi tôi đồng ý với các phương pháp hay nhất, tài liệu lăng kính nêu rõ rằng bạn có thể sử dụng phương pháp Khởi tạo phương pháp của bạn cũng như "Đăng ký dịch vụ được chia sẻ với vùng chứa phụ thuộc của ứng dụng." http://msdn.microsoft.com/en-us/library/gg405479%28v=pandp.40%29.aspx – Console

+2

Nếu chúng ta không được biết về thùng chứa, thì làm cách nào các mô-đun có thể đăng ký các dịch vụ được chia sẻ mới? – Benjamin

+0

'ComposeExportedValue' đã đề cập là một phương thức mở rộng trong 'System.ComponentModel.Composition.AttributedModelServices' – jan

0

Lưu ý rằng tôi đang sử dụng phiên bản cũ hơn của Prism và tôi đang sử dụng nó với UnityContainer nhưng các nguyên tắc tương tự sẽ được áp dụng.

Xác định lớp Mô-đun của bạn để có một vùng chứa trong hàm tạo.

Dưới đây là một ví dụ sử dụng Unity:

public class Module : IModule 
{ 
    public static IUnityContainer Container; 

    public Module(IUnityContainer container) 
    { 
     Container = container; 
    } 
} 

Nếu bạn định nghĩa một constructor mà phải mất một container, nó sẽ được gọi là theo phương pháp ApplicationBootstrapper.Run().

Tôi đã thử nghiệm với một hàm tạo ít tham số mặc định và một hàm tạo quá tải nhận vùng chứa và hàm tạo thứ hai được gọi.

Tôi cũng đã chọn chỉ có hàm tạo mặc định và được gọi. Tôi sẽ đề nghị bạn thay đổi constructor của bạn để thêm một tham số dùng một container.

Có vùng chứa trong lớp mô-đun của bạn sẽ cho phép bạn đăng ký các loại trong phương thức Khởi tạo.

Đối với ServiceLocator, đó là một mô hình hơi khác nhau mà tôi khuyên bạn nên sử dụng trong trường hợp bạn không thể nhận được phụ thuộc của bạn được tạo ra bởi các container vì lý do nào.

+0

Tôi đã cố gắng làm điều đó. MEF sử dụng kiểu CompositionContainer thay vì IUnityContainer của Unity. Nhưng constructor của tôi với tham số đã gõ là CompositionContainer không thực thi. –

+0

@reito: Bạn cũng có một hàm tạo mặc định và cách bạn gọi phương thức chạy ApplicationBootstrapper? – Gilles

+0

Tôi không còn nhà thầu nào nữa, chỉ có người này. Phương thức Khởi động Bootstrapper đang gọi trong phương thức OnStartup của lớp Ứng dụng của tôi. –