Tôi đã sử dụng Ninject cụ thể trong ứng dụng MVC. Cách bạn thực hiện điều này với Ninject là trong cấu hình hoặc ràng buộc của các phụ thuộc của bạn. Khi bạn làm điều này, bạn chỉ định cách bạn muốn quản lý thời gian tồn tại đối tượng của bạn. Trong hầu hết các trường hợp của một ứng dụng web, các đối tượng của bạn sẽ theo yêu cầu như bạn đã chỉ ra trong câu hỏi của bạn.
Một điều tôi đã nhận thấy trong câu hỏi của bạn là của bạn DomainContext đã được tạo ra bởi một IDomainService đối tượng và được sử dụng bởi các đối tượng khác. Nếu đối tượng dịch vụ miền là một loại nhà máy cho DomainContext, thì bạn không có nhiều vấn đề - điều này sẽ trở thành một bài tập về cách bạn định cấu hình Ninject để cung cấp các đối tượng cụ thể và chèn phụ thuộc.
Dưới đây là hướng dẫn chung về cách bạn sẽ cấu trúc ứng dụng của bạn - hãy nhớ tôi không có hiểu biết đầy đủ các giao diện và các lớp học của bạn:
public class GlobalApplication : NinjectHttpApplication {
protected override void RegisterRoutes(RouteCollection routes) {
// Your normal route registration goes here ...
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = "" }
);
}
// This function is resposible for creating a Ninject kernel. This is where
// the magic starts to happen.
protected override IKernel CreateKernel() {
var modules = new IModule[] {
new AutoWiringModule(),
new AutoControllerModule(
Assembly.GetExecutingAssembly()),
new ServiceModule()
};
return new StandardKernel(modules);
}
}
Lưu ý ở trên rằng cách dễ nhất để có được Ninject làm việc là lấy được lớp ứng dụng của bạn từ lớp NinjectHttpApplication. Bạn cần phải thay đổi RegisterRoutes thành phương thức ghi đè và cũng sẽ được yêu cầu triển khai phương thức có tên là CreateKernel. Phương thức CreateKernel có trách nhiệm trả về hạt nhân Ninject mà chính nó là vùng chứa IoC.
Trong CreateKernel phương pháp, các Ninject-cung cấp AutoControllerModule quét lắp ráp cho các lớp điều khiển MVC và đăng ký chúng bằng vùng chứa. Điều này có nghĩa là các phụ thuộc vào các bộ điều khiển này có thể được Ninject tiêm vào khi nó trở thành nhà cung cấp bộ điều khiển cho ứng dụng. Lớp ServiceModule là lớp bạn cần tạo để đăng ký tất cả các dịch vụ của mình với Ninject. Tôi đoán nó sẽ trông giống như thế này:
internal class ServiceModule : StandardModule {
public override void Load() {
Bind<IDomainService>()
.To<MyDomainService>()
.Using<OnePerRequestBehavior>();
Bind<DomainContext>()
.ToMethod(ctx => ctx.Kernel.Get<IDomainService>().CurrentDomainContext)
.Using<OnePerRequestBehavior>();
Bind<IService>()
.To<MyServiceType>()
.Using<OnePerRequestBehavior>();
}
}
Ninject có giao diện khá thông thạo để cấu hình. Lưu ý ở trên mỗi câu lệnh về cơ bản liên kết một lớp cụ thể với một giao diện mà nó thực hiện. Cụm từ "Sử dụng" trong câu lệnh cho biết hạt nhân Ninject rằng đối tượng sẽ chỉ tồn tại trong vòng đời của yêu cầu. Vì vậy, ví dụ, điều này có nghĩa là bất cứ khi nào một đối tượng IDomainService được yêu cầu từ hạt nhân Ninject trong cùng một yêu cầu, cùng một đối tượng sẽ được trả về.
Đối với các đối tượng bối cảnh của bạn, tôi đang sử dụng dịch vụ miền của bạn tạo ra các ngữ cảnh này và hoạt động như một loại nhà máy. Về vấn đề đó, tôi ràng buộc các trường hợp DomainContext các lớp ở trên được tạo ra bằng cách nhận giá trị của thuộc tính được gọi là CurrentDomainContext tắt số IDomainService. Đó là những gì lambda trên hoàn thành. Điều tốt đẹp về liên kết "ToMethod" trong Ninject là bạn có quyền truy cập vào một đối tượng bối cảnh kích hoạt Ninject cho phép bạn giải quyết các đối tượng bằng cách sử dụng hạt nhân. Đó chính xác là những gì chúng tôi làm để có được ngữ cảnh miền hiện tại.
Các bước tiếp theo là đảm bảo các đối tượng của bạn chấp nhận phụ thuộc đúng cách. Ví dụ: bạn nói rằng ITrainingService chỉ được sử dụng trong lớp TrainingController. Vì vậy, trong trường hợp đó, tôi sẽ đảm bảo rằng TrainingController có một hàm tạo chấp nhận tham số ITrainingService. Trong hàm tạo đó, bạn có thể lưu tham chiếu đến số ITrainingService trong biến thành viên. Như trong:
public class TrainingController : Controller {
private readonly ITrainingService trainingService;
public TrainingController(ITrainingService trainingService) {
this.trainingService = trainingService;
}
// ... rest of controller implementation ...
}
Hãy nhớ rằng Ninject đã đăng ký tất cả các bộ điều khiển của bạn với kernel Ninject, vì vậy khi điều khiển này được tạo ra và hành động của nó được gọi, bạn sẽ có một tham chiếu đến ITrainingService bằng cách của biến thành viên trainingService.
Hy vọng điều này sẽ giúp bạn. Sử dụng container IoC có thể trở nên khá khó hiểu ở lần. Lưu ý, tôi khuyên bạn nên kiểm tra các Ninject documentation - đó là một giới thiệu rất tốt bằng văn bản cho Ninject cũng như các khái niệm DI/IoC. Tôi cũng đã bỏ qua thảo luận về AutoWiringModule được hiển thị ở trên; tuy nhiên, Nate Kohari (tác giả của Ninject) có a good write-up trên blog của anh ấy về tính năng này.
Chúc may mắn!
Liên kết bị hỏng, lời khuyên được thay thế bởi câu trả lời hoàn chỉnh của Peter. (Một lỗi đặc biệt sai là đề xuất các hành vi kích hoạt (InRequestScope trong câu trả lời của Peter là cách tiếp cận chính xác)). Đề xuất xóa câu trả lời này. (Không greviously sai nên không -1 nhưng không xa nó) –