Điều này thực sự đơn giản để thực hiện khi bạn hiểu rằng DI có khoảng mẫu và nguyên tắc, không phải công nghệ.
Để thiết kế các API theo một cách DI container-agnostic, hãy làm theo những nguyên tắc chung:
Chương trình để một giao diện, không phải là một thực hiện
Nguyên tắc này thực sự là một trích dẫn (từ bộ nhớ mặc dù) từ Design Patterns, nhưng nó luôn luôn là mục tiêu thực sự của bạn. DI chỉ là phương tiện để đạt được mục tiêu đó.
Áp dụng các nguyên tắc Hollywood
Các Nguyên tắc Hollywood về DI nói: Đừng gọi DI container, nó sẽ gọi cho bạn.
Không bao giờ trực tiếp yêu cầu sự phụ thuộc bằng cách gọi một vùng chứa từ bên trong mã của bạn. Yêu cầu nó ngầm bằng cách sử dụng Constructor Injection.
Sử dụng Constructor tiêm
Khi bạn cần một sự phụ thuộc, yêu cầu nó tĩnh thông qua các nhà xây dựng:
public class Service : IService
{
private readonly ISomeDependency dep;
public Service(ISomeDependency dep)
{
if (dep == null)
{
throw new ArgumentNullException("dep");
}
this.dep = dep;
}
public ISomeDependency Dependency
{
get { return this.dep; }
}
}
Chú ý cách lớp dịch vụ đảm bảo bất biến của nó. Khi một cá thể được tạo, sự phụ thuộc được đảm bảo có sẵn vì sự kết hợp của Điều khoản bảo vệ và từ khóa readonly
.
Sử dụng Abstract Factory nếu bạn cần một đối tượng ngắn ngủi
Dependencies tiêm với Constructor tiêm có xu hướng tồn tại lâu dài, nhưng đôi khi bạn cần một đối tượng trong thời gian ngắn, hoặc để xây dựng phụ thuộc dựa trên một giá trị chỉ được biết đến trong thời gian chạy.
Xem this để biết thêm thông tin.
Soạn chỉ ở Moment Chịu trách nhiệm cuối
Giữ đối tượng tách rời cho đến phút cuối. Thông thường, bạn có thể chờ và kết nối mọi thứ trong điểm vào của ứng dụng. Đây được gọi là Thành phần gốc.
Xem thêm chi tiết ở đây:
Đơn giản hóa bằng cách sử dụng mặt tiền
Nếu bạn cảm thấy rằng các API kết quả trở nên quá phức tạp đối với người dùng mới làm quen, bạn luôn có thể cung cấp một số lớp học Facade mà encapsu sự kết hợp phụ thuộc muộn.
Để cung cấp Mặt tiền linh hoạt có khả năng phát hiện cao, bạn có thể cân nhắc cung cấp Trình tạo thông thạo. Một cái gì đó như thế này:
public class MyFacade
{
private IMyDependency dep;
public MyFacade()
{
this.dep = new DefaultDependency();
}
public MyFacade WithDependency(IMyDependency dependency)
{
this.dep = dependency;
return this;
}
public Foo CreateFoo()
{
return new Foo(this.dep);
}
}
Điều này sẽ cho phép người dùng tạo ra một Foo mặc định bằng cách viết
var foo = new MyFacade().CreateFoo();
Nó sẽ, tuy nhiên, rất có thể phát hiện rằng nó có thể cung cấp một sự phụ thuộc tùy chỉnh, và bạn có thể viết
var foo = new MyFacade().WithDependency(new CustomDependency()).CreateFoo();
Nếu bạn cho rằng lớp MyFacade đóng gói rất nhiều phụ thuộc khác nhau, tôi hy vọng rõ ràng cách nó sẽ cung cấp mặc định phù hợp khi vẫn làm nsibility có thể khám phá.
FWIW, rất lâu sau khi viết câu trả lời này, tôi mở rộng trên các khái niệm trong tài liệu này và đã viết một bài đăng blog còn khoảng DI-Friendly Libraries, và một người bạn đồng gửi về DI-Friendly Frameworks.
Tham chiếu mới cho bài viết liên kết bị hỏng (SOLID): http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod –