2014-05-01 21 views
10

Tôi mới sử dụng AutoFac và hiện đang sử dụng các mô-đun tùy chỉnh bên trong cấu hình ứng dụng của mình để khởi động một số hệ thống F # lõi. Mã tôi đang sử dụng làGiải quyết các phụ thuộc AutoFac bên trong Module class

var builder = new ContainerBuilder(); 
builder.RegisterType<DefaultLogger>().As<IDefaultLogger>(); 
builder.RegisterModule(new ConfigurationSettingsReader("autofac")); 
builder.Build(); 

Và bên trong cấu hình ứng dụng của tôi Tôi có logic thích hợp để khởi động hệ thống liên quan. Tôi muốn có quyền truy cập vào DefaultLogger bên trong Modules của tôi. Siêu dữ liệu cho các lớp cơ sở Mô-đun có các tùy chọn sau đây có sẵn cho tôi:

protected virtual void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration); 

protected virtual void AttachToRegistrationSource(IComponentRegistry componentRegistry, IRegistrationSource registrationSource); 

public void Configure(IComponentRegistry componentRegistry); 

protected virtual void Load(ContainerBuilder builder); 

tôi đã chỉ được sử dụng tải cho đến nay và tôi không thể nhìn thấy bất kỳ phương pháp trên người xây dựng mà sẽ cho phép tôi để có được vào khai thác gỗ dịch vụ.

+0

Đây có phải là câu hỏi trùng lặp với http://stackoverflow.com/questions/23413211/autofac-cannot-resolve-dependency-in-module không? –

Trả lời

3

Câu trả lời hóa ra là vô cùng đơn giản. Tôi vừa thêm IComponentContext làm phụ thuộc vào việc triển khai Mô-đun của tôi

public class LocalActorSystemModule : Module { 
    private IComponentContext m_ComponentContext; // A service for resolving dependencies required by this module 

    public LocalActorSystemModule(IComponentContext componentContext) { 
     m_ComponentContext = componentContext; 
    } 

Và để AutoFac tiêm IComponentTiếp theo cho tôi. Bằng cách đó tôi có thể giải quyết bất kỳ sự phụ thuộc nào mà tôi yêu cầu bên trong module.

+0

bạn sẽ đăng ký LocalActorSystemModule như thế nào? –

+1

Điều này không hiệu quả đối với tôi. Tôi tiêm IComponentContext thông qua các constructor Module, nhưng khi tôi đã cố gắng sử dụng nó trong 'AttachToComponentRegistration' nó không thể giải quyết những gì tôi muốn nó vì các thành phần chưa được đăng ký. – emragins

+0

Điều này chỉ có thể hoạt động đối với mô-đun nếu mô-đun được đăng ký chính nó và sau khi tải (phụ thuộc bắt buộc, ví dụ: mô-đun được tải), nếu không bạn không thể giải quyết được. IMHO, IComponentContext được cho là được đưa vào đăng ký dịch vụ (tự động), nhưng không được sử dụng trong các mô-đun. Tôi nghĩ rằng hành vi này không thực sự có thể đoán trước được và tôi sẽ không khuyên bạn nên làm điều đó. Hãy suy nghĩ về việc sử dụng IComponentContext trong khi mô-đun không thực sự được tải ... kết quả sẽ là gì trước và sau khi tải? – Beachwalker

6

Khi đăng ký một cái gì đó trong module của bạn với autofac thay vì sử dụng phương pháp RegisterType bạn có thể sử dụng phương pháp đăng ký:

builder.Register(c => 
    { 
     IComponentContext ctx = c.Resolve<IComponentContext(); 
     IDefaultLogger logger = ctx.Resolve<IDefaultLogger>(); 
     ...do something with logger... 
     return ...return object you want to register...; 
    }); 
+1

Điều này không thực sự giúp kịch bản tôi mô tả. Tôi hiểu rằng tôi có thể giải quyết các phụ thuộc bằng cách sử dụng một IComponentContext nhưng tôi cần truy cập vào một bên trong Module. –

+0

Bạn không được phép rời khỏi tiêu điểm ở đây để đặt biến trong phạm vi bên ngoài (mô-đun trong ví dụ của mình). Bằng cách này, bạn chỉ có thể đăng nhập bên trong đăng ký. Dù sao, snipit này cho thấy "cách đúng" của việc sử dụng vùng chứa/ngữ cảnh, vì vậy +1. Có lẽ Jesse cần phải sử dụng phạm vi cuộc đời và một container có một logger và xây dựng một container có được logger tiêm mà chính nó tải các mô-đun được cung cấp bởi đầu tiên (hmm, âm thanh quá phức tạp). – Beachwalker

2

Quy tắc để sử dụng mọi IoC/DI Vùng chứa: Giải quyết một lần! => sau đó bạn nhận được tất cả các phụ thuộc được giải quyết cho đối tượng bạn yêu cầu. Nếu bạn cố gắng giải quyết nhiều lần, hãy đăng ký các đối tượng khác (trong khi chờ đợi) bạn bị kẹt trong địa ngục. Có thật không. Nếu bạn muốn truy xuất các đối tượng cho các mục đích khác nhau tại các địa điểm và thời điểm khác nhau (được giải quyết từ đăng ký trung tâm), bạn có thể tìm kiếm Service Locator Pattern thay thế (nhưng điều này thường được mô tả là Anti-Pattern).

Modules có mục đích để gói đăng ký có liên quan (có điều kiện) như statet trong Autofac documentation:

Module là một lớp nhỏ có thể được sử dụng để bó lên một bộ các thành phần liên quan đến đằng sau một 'mặt tiền 'để đơn giản hóa cấu hình và triển khai .

... vì vậy nếu chỉ là tổng đăng ký và vùng chứa chưa được tạo, bạn không thể giải quyết và sử dụng thành phần (ngay cả trước đây đã đăng ký) ngay lập tức (trừ khi gọi phương thức trên người đăng ký) chính nó thông qua OnActivate * móc hoặc khi sử dụng đăng ký cá thể, nhưng tôi nghĩ rằng đây không phải là trường hợp cho ví dụ của bạn). Các thành phần chỉ ở trạng thái đăng ký nhưng hoàn cảnh không sẵn sàng để giải quyết. Điều gì sẽ xảy ra nếu bạn ghi đè đăng ký trong một Mô-đun khác? Sau đó, bạn sẽ tiêm các đối tượng khác nhau ... ý tưởng tồi. Có lẽ bạn nên suy nghĩ lại về thiết kế ứng dụng của bạn và đối tượng nào có trách nhiệm nào.

Nhân tiện: Ghi nhật ký là mối quan tâm cắt ngang thường được "tiêm/giải quyết" bằng cách gọi một nhà máy hoặc dịch vụ tĩnh riêng biệt thay vì thực hiện việc xây dựng/xử lý thuộc tính (xem cách sử dụng Common.Logging chẳng hạn).

public class MyModule : Module 
{ 
    private static readonly ILog Log = LogManager.GetLogger<MyModule>(); 

    protected override void Load(ContainerBuilder builder) 
    { 
     Log.Debug(msg => msg("Hello")); // log whatever you want here 
    } 
} 

Bạn cũng có thể thử sử dụng AOP thư viện và dệt phụ thuộc vào mô-đun (sử dụng phản ánh).Nhưng tôi không nghĩ rằng nó có giá trị để thử chỉ để đăng nhập vào một Module.

Dù sao: @ mr100 đã hiển thị đúng cách sử dụng trong quá trình đăng ký. Ở đó bạn cũng có thể xử lý kích hoạt, vv nhưng không đăng nhập vào Module.

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