Điều này thực sự đơn giản để làm một khi bạn hiểu rằng DI là về các mẫu và nguyên tắc , không phải công nghệ.
Để thiết kế API theo cách không tin tưởng DI Container, hãy làm theo các nguyên tắc chung sau:
Chương trình cho một giao diện, không phải là một triển khai
Nguyên tắc này thực sự là một trích dẫn (từ bộ nhớ) từ Thiết kế mẫu , nhưng nó phải luôn là mục tiêu thực sự của bạn . DI chỉ là một phương tiện để đạt được kết thúc đó .
Áp dụng nguyên tắc Hollywood
Nguyên tắc Hollywood theo thuật ngữ DI nói: Đừng gọi DI Container, nó sẽ gọi cho bạn .
Không bao giờ yêu cầu trực tiếp cho một phụ thuộc bằng cách gọi một container từ trong mã của bạn. Yêu cầu nó hoàn toàn bằng cách sử dụng Con Contortor tiêm .
Sử dụng tiêm xây dựng
Khi bạn cần một phụ thuộc, yêu cầu nó tĩnh thông qua hàm tạo:
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; }
}
}
Lưu ý cách lớp Service đảm bảo các bất biến của nó. Khi một thể hiện được tạo, sự phụ thuộc được đảm bảo có sẵn do sự kết hợp của Điều khoản bảo vệ và readonly
từ khóa.
Sử dụng Tóm tắt Factory nếu bạn cần một đối tượng có thời gian tồn tại ngắn
Các phụ thuộc được tiêm Con Contortor 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 tồn tại trong thời gian ngắn hoặc để xây dựng sự phụ thuộc dựa trên giá trị chỉ được biết trong thời gian chạy.
Xem điều này để biết thêm thông tin.
Chỉ sáng tác tại thời điểm có trách nhiệm cuối cùng
Giữ các đối tượng tách rời cho đến cuối cùng. Thông thường, bạn có thể đợi 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 .
Thêm chi tiết tại đâ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 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 vài lớp Mặt tiền gói gọn các kết hợp phụ thuộc chung.
Để cung cấp Mặt tiền linh hoạt với mức độ khám phá cao, bạn có thể xem xét việc cung cấp Fluent Builders. 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 Foo mặc định bằng cách viết
var foo = new MyFacade().CreateFoo();
Tuy nhiên, rất có thể phát hiện ra rằng có thể cung cấp một 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 tưởng tượng rằng lớp MyFacade gói gọn rất nhiều phụ thuộc khác nhau, tôi hy vọng nó rõ ràng làm thế nào nó sẽ cung cấp các giá trị mặc định phù hợp trong khi vẫn có thể mở rộng được.
FWIW, rất lâu sau khi viết câu trả lời này, tôi đã mở rộng các khái niệm trong tài liệu này và viết một bài đăng blog dài hơn về Thư viện thân thiện với DI và một bài đăng đồng hành về Khung thân thiện với DI .