2012-09-05 47 views
15

Tôi có một dự án mà Ninject được sử dụng làm thùng chứa IoC. Mối quan tâm của tôi là rất nhiều lớp học có loại đó của cấu trúc:Tiêm phụ thuộc lười biếng

[Inject] 
public HomeController(
    UserManager userManager, RoleManager roleManager, BlahblahManager blahblahManager) { 
    _userManager = userManager; 
    _roleManager = roleManager; 
    _blahblahManager = blahblahManager; 
} 

gì nếu tôi không muốn có tất cả các trường hợp của các lớp này cùng một lúc?

Cách thức, khi tất cả các lớp học này được bao bọc bởi Lazy<T> và được truyền cho nhà xây dựng không chính xác những gì tôi cần. Các phiên bản T chưa được tạo nhưng Lazy<T> trường hợp đã được lưu trữ trong bộ nhớ.

Đồng nghiệp của tôi đề xuất tôi sử dụng mẫu Nhà máy để kiểm soát tất cả các cảnh báo, nhưng tôi không chắc chắn rằng IoC có lỗi thiết kế tuyệt vời như vậy.

Có cách giải quyết nào cho tình huống này hay IoC thực sự có khiếm khuyết lớn như vậy trong thiết kế của nó? Có lẽ tôi nên sử dụng một container IoC?

Mọi đề xuất?

+0

Điều gì thực sự là vấn đề của bạn? Tại sao bạn không muốn những trường hợp này? –

+2

Tôi có thể muốn UserManager trong quá trình hoạt động của bộ điều khiển, nhưng không cần RoleManager và ngược lại. Nếu bạn nói về các trường hợp Lazy , thì đây không phải là vấn đề lớn để có chúng trong bộ nhớ, nhưng đây có phải là cách duy nhất không? – xwrs

+1

Tại sao nó là một việc lớn đối với 'UserManager' và' RoleManager'? Các nhà xây dựng của bạn không nên làm việc nặng. –

Trả lời

36

Dường như với tôi rằng bạn đang làm premature optimization: đừng làm điều đó.

Các nhà xây dựng dịch vụ của bạn nên làm nothing more hơn là lưu trữ các phụ thuộc mà nó cần trong các trường riêng tư. Trong trường hợp đó việc tạo ra một vật thể như vậy thực sự là trọng lượng nhẹ. Đừng quên rằng việc tạo đối tượng trong .NET thực sự rất nhanh. Trong hầu hết các trường hợp, từ góc độ hiệu suất, nó không quan trọng liệu những phụ thuộc đó có được tiêm hay không. Đặc biệt là khi so sánh với số lượng đối tượng, phần còn lại của ứng dụng của bạn (và các khung công tác bạn sử dụng) đang loại bỏ. Chi phí thực tế là khi bạn bắt đầu sử dụng dịch vụ web, cơ sở dữ liệu hoặc hệ thống tệp (hoặc I/O nói chung), vì chúng gây ra sự chậm trễ lớn hơn nhiều. Nếu việc tạo ra thực sự đắt tiền, bạn thường nên ẩn việc tạo ra sau một Virtual Proxy thay vì tiêm một Lazy<T> trong mọi người tiêu dùng, vì điều này cho phép mã ứng dụng phổ biến không biết thực tế là có cơ chế trì hoãn việc tạo (cả mã ứng dụng và mã thử nghiệm của bạn đang trở nên phức tạp hơn khi bạn làm điều này).

Chương 6 của Dependency Injection in .NET, second edition chứa một cuộc thảo luận chi tiết hơn về các proxy lười và ảo.

Tuy nhiên, một Lazy<T> chỉ tiêu thụ 20 byte bộ nhớ (và 24 bytes khác cho nó quấn Func<T>, giả sử một quá trình 32bit), và tạo ra một thể hiện Lazy<T> là thực tế miễn phí. Vì vậy, không cần phải lo lắng về điều này, ngoại trừ khi bạn đang ở trong một môi trường với những hạn chế về bộ nhớ thực sự chặt chẽ.

Và nếu mức tiêu thụ bộ nhớ là vấn đề, hãy thử đăng ký dịch vụ với tuổi thọ lớn hơn thoáng qua. Bạn có thể thực hiện theo yêu cầu, theo yêu cầu web hoặc singleton. Tôi thậm chí sẽ nói rằng khi bạn ở trong môi trường tạo đối tượng mới là một vấn đề, bạn có lẽ chỉ nên sử dụng dịch vụ singleton (nhưng không chắc bạn đang làm việc trên môi trường như vậy, vì bạn đang xây dựng một ứng dụng web) .

Lưu ý rằng Ninject là một trong các thư viện DI chậm hơn cho .NET. Nếu điều đó gây phiền hà cho bạn, switch to a faster container. Một số thùng chứa có hiệu suất gần bằng cách tạo mới đồ thị đối tượng bằng tay. nhưng bằng mọi cách, hãy làm hồ sơ này, nhiều nhà phát triển chuyển thư viện DI vì những lý do sai.

Lưu ý rằng việc sử dụng Lazy<T> là sự phụ thuộc là leaky abstraction (vi phạm Dependency Inversion Principle). Vui lòng đọc this answer để biết thêm thông tin.

+0

Cảm ơn bạn. Bạn đã hiểu rõ hơn về tình hình của tôi. – xwrs

+0

Tôi không nghĩ rằng đó là tối ưu hóa sớm, với lập luận này có vẻ như không bao giờ có nhu cầu về Lười biếng, việc tạo ra một đối tượng không nặng nhưng bạn không biết có bao nhiêu đối tượng đang tạo ra trong hàm tạo của nó. Và mở một số tài nguyên từ xa có thể không được sử dụng. –

0

New

Steven là đúng khi nói rằng điều này có vẻ như tối ưu hóa quá sớm. Việc xây dựng các đối tượng này rất nhanh và thường không bao giờ là nút cổ chai.

Tuy nhiên sử dụng Lười biếng để thể hiện sự phụ thuộc bạn không cần ngay là một mô hình phổ biến trong khuôn khổ Dependency Injection. Actofac là một trong những vùng chứa được xây dựng để hỗ trợ cho various wrapping types. Tôi chắc rằng cũng có phần mở rộng cho Ninject, có thể xem cái này, Ninject Lazy.

+1

Thực tế là các thùng chứa DI có hỗ trợ cho Lazy , không làm cho nó phù hợp để cho mã ứng dụng của bạn phụ thuộc vào sự phụ thuộc Lười biếng . Nhiều vùng chứa DI hỗ trợ các tính năng không quảng cáo các phương pháp hay nhất. Từ góc độ Dependency Injection, Lazy là một trừu tượng bị rò rỉ. Vui lòng đọc [this] (https://stackoverflow.com/a/21724609/264697) để biết giải thích lý do tại sao rò rỉ Lazy. – Steven

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