2009-07-21 44 views
7

Tôi đang thiết kế trang web có kích thước trung bình bằng cách sử dụng công nghệ asp.net mvc. Tất cả logic nghiệp vụ được tổ chức thành IServices (như IDomainService, IUserService, IAuthService, ITrainingService). Tất cả các dịch vụ đang sử dụng IRepositories. Tôi đang sử dụng Ninject 1.5 cho các dịch vụ dây với bộ điều khiển và có vẻ như hoạt động hoàn hảo.Kiến trúc kích thước trung bình asp mvc - sử dụng ninject và tạo đối tượng

Hiện có một chủ đề mà tôi không biết cách xử lý. Một số dịch vụ tạo ra các ngữ cảnh (theo yêu cầu) - ví dụ IDomainService tạo ra DomainContext (theo yêu cầu) cần thiết cho IUserService. ITrainingService chỉ được sử dụng trong TrainingController, chỉ có thể truy cập bởi người dùng được ủy quyền và ITrainingService yêu cầu UserContext (cũng theo yêu cầu) để biết ai đang đào tạo.

Đây là dự án đầu tiên của tôi sử dụng vùng chứa IoC. Có bất kỳ mẫu thiết kế hay giản đồ mã nào để giải quyết nó không? Tôi nghĩ rằng tôi có thể điền vào đối tượng bối cảnh bằng cách sử dụng ActionFilters nhưng làm thế nào để quản lý cuộc đời của họ và nơi để đặt chúng để có thể truy cập cho IServices? (trong một cách ngây thơ)

Trả lời

10

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!

0

Tôi không chắc chắn nếu tôi hiểu vấn đề của bạn hoàn toàn, hy vọng rằng lời khuyên này có thể giúp bạn.

Khi sử dụng thùng chứa IoC, bạn cho phép thùng chứa xử lý toàn bộ đối tượng của đối tượng. Tôi đã chỉ sử dụng Castle Windsor và StructureMap cho tiêm phụ thuộc vì vậy tôi không thể cung cấp cho bạn một ví dụ cụ thể để làm thế nào để làm điều này với Ninject.

Xem qua tài liệu Ninject Tôi nghĩ bạn muốn xem Activation Behaviours để chỉ định quản lý tuổi thọ đối tượng.

Hy vọng điều này sẽ hữu ích.

+0

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ó) –

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