2011-01-23 32 views
6

Tôi đang học TDD. Tôi biết về tiêm phụ thuộc, theo đó bạn đặt các phụ thuộc của lớp trong các tham số của hàm tạo và chuyển chúng vào, đi qua trong các triển khai mặc định từ constructor mặc định ví dụ;Các lớp thử nghiệm đơn vị trong dự án web ASP.NET MVC có phải là một ví dụ hay không?

public AccountController() : this(RepositoryFactory.Users()) 
{ 
} 

public AccountController(IUserRepository oUserRepository) 
{ 
m_oUserRepository = oUserRepository; 
} 

RepositoryFactory là một lớp tĩnh đơn giản mà trả về triển khai lựa chọn cho việc xây dựng hiện hành

Nhưng mặc định ASP.NET MVC dự án ứng dụng web không làm điều này, thay vào đó là DI có dạng của công chúng các thuộc tính được gán trong bộ khởi tạo đối tượng trong lớp thử nghiệm ví dụ; từ AccountController.cs:

protected override void Initialize(RequestContext requestContext) 
{ 
if (FormsService == null) 
    { FormsService = new FormsAuthenticationService(); } 
if (MembershipService == null) 
    { MembershipService = new AccountMembershipService(); } 

base.Initialize(requestContext); 
} 

Và trong AccountControllerTest.cs lớp thử nghiệm:

private static AccountController GetAccountController() 
{ 
AccountController controller = new AccountController() 
{ 
    FormsService = new MockFormsAuthenticationService(), 
    MembershipService = new MockMembershipService(), 
    Url = new UrlHelper(requestContext), 
}; 
//snip 
} 

Bây giờ lớp AccountController tôi có hai cách tiếp cận để Dependency Injection. Tôi nên sử dụng cái nào? Xây dựng tiêm hoặc tài sản công cộng?

Am nghĩ constructor tiêm ...

Việc sử dụng ASP.NET MVC tài sản công cộng như thế bởi vì bạn cần phải cung cấp một cách cụ thể của tiêm vào các nhà xây dựng, và cơ bản "tạo mới" ứng dụng web cần phải được chung chung như là một điểm khởi đầu?

Trả lời

11

Ví dụ trong ASP.NET MVC là trình diễn tuyệt vời về cách không phải để sử dụng DI.

Trước hết, sử dụng hàm tạo mặc định cũng như hàm tạo quá tải giới thiệu mơ hồ: lớp có kiểm soát các phụ thuộc của riêng nó hay không nhận chúng từ bên ngoài? Rõ ràng, nó không thể thực sự quyết định.

Thứ hai, việc triển khai mặc định giới thiệu khớp nối chặt chẽ vì bạn không thể tạo phiên bản triển khai mặc định mới mà không cần tham chiếu đến nó. Tuy nhiên, whole point of DI is to enable loose coupling.

Thật không may, chúng tôi thấy thành ngữ này rất nhiều. Trong my book Tôi gọi nó là Khốn nạn chống mẫu; Tôi đã nâng tên từ một trong số nhiều bài đăng trên blog được đề xuất của Oren Eini/Ayende Rahien, trong đó he walks through a very similar example.

Là lời khuyên chung, tôi khuyên bạn nên sử dụng Tiêm xây dựng trong phần lớn các trường hợp. Thật dễ dàng để thực hiện và có ngữ nghĩa rất mạnh: nó buộc người tiêu dùng cung cấp một thể hiện của sự phụ thuộc, có hiệu quả nói rằng sự phụ thuộc là bắt buộc.

Tiêm thuộc tính, mặt khác, ngụ ý rằng phụ thuộc là tùy chọn, vì trình biên dịch không buộc bạn gán giá trị. Trong hầu hết các trường hợp, các phụ thuộc không thực sự là tùy chọn, vì vậy việc sử dụng mẫu này nên rất hiếm.

+0

Cảm ơn Mark, giờ đây đã có ý nghĩa.Có mơ hồ hay thuận tiện? Đối với bộ điều khiển tôi chỉ thấy hai công dụng (trong sự thiếu hiểu biết của tôi); ứng dụng đã biên dịch và dự án thử nghiệm. Ứng dụng được biên dịch chỉ sử dụng các triển khai mặc định từ hàm tạo mặc định. Điều đó sẽ nhanh hơn việc sử dụng một container IOC phải không? –

+0

Ah ok Tôi nghĩ rằng tôi nhận được nó. Tôi đang đọc về IOC lồng nhau nơi phụ thuộc có phụ thuộc. Với IOC, điều này được giải quyết với một dòng đơn như IoC.Resolve (); –

+0

Đánh dấu, bạn có thể giúp tôi hiểu rõ hơn lý do tại sao không sử dụng "Tiêm Bastard"? Như tôi thấy, lớp vẫn cho phép khớp nối lỏng lẻo trong đó bạn không phải sử dụng constrcutor mặc định. Phải thừa nhận rằng, mã có sự phụ thuộc tĩnh vào RepositoryFactory, nhưng bạn không phải sử dụng nó. Ngoài ra, "sự mơ hồ" là một tính năng: Sử dụng các phụ thuộc mặc định hoặc tự chèn của riêng bạn. Có chuyện gì vậy? –

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