2012-08-16 17 views
13

Ứng dụng của tôi bao gồm một số hội đồng back-end (bao gồm lớp kho dữ liệu Entity Framework) được chia sẻ bởi một số hội đồng front-end (bao gồm dịch vụ Windows và một ứng dụng web MVC3).Nơi để định vị mô-đun Ninject trong ứng dụng nhiều tầng

Sự hiểu biết của tôi về quy trình liên kết Ninject là mỗi assembly có chứa các kiểu tiêm cũng nên chứa một mô-đun Ninject xác định các ràng buộc mặc định cho các kiểu này. Tập các module được định nghĩa sau đó sẽ được nạp vào hạt nhân Ninject của các hội đồng tiêu thụ.

Tuy nhiên, tôi đang gặp sự cố, vì phạm vi ràng buộc bắt buộc không phải lúc nào cũng nhất quán. Ví dụ, dự án MVC của tôi cần phải liên kết với bối cảnh dữ liệu InRequestScope, trong khi dịch vụ Windows liên kết với cùng một lớp InThreadScope. Tôi có thể giải quyết vấn đề này bằng cách di chuyển tất cả các mô-đun vào các dự án front-end và do đó duy trì các bản sao riêng biệt của mỗi mô-đun cho mỗi kịch bản sử dụng, nhưng điều này có vẻ như hacky, vì nó sao chép nhiều nội dung mô-đun qua nhiều dự án .

Có cách nào hay nhất về nơi mô-đun phải được đặt trong ứng dụng nhiều tầng và cách tôi có thể điều chỉnh việc này với nhu cầu về sự khác biệt về ràng buộc giữa các dự án?

Rất cám ơn cho đề xuất của bạn,

Tim

+0

cũng xem http://stackoverflow.com/questions/1699197/how-do-you-organise-your-ninject-modules (IIRC này Q là một số nhưng đây là điều tốt nhất tôi có bây giờ) –

+0

Cảm ơn Ruben. Bạn nói đúng là có nhiều điểm chung giữa hai câu hỏi này. Tôi đặc biệt thích đề xuất của bạn về việc truyền các tham số thời gian chạy vào các mô-đun nằm trong các hội đồng hỗ trợ - rất linh hoạt. –

+0

Hmm; đó là một số thời gian trước đây (không cố gắng để pimp câu trả lời của tôi trong bất kỳ cách nào). Tôi có thể có nghĩa đen có nghĩa là * đi qua các thông số * trở lại trong ngày - nói chung tôi sẽ cố gắng làm điều đó thông qua các giao diện càng nhiều càng tốt. Ngoài ra, đó là trước khi http://manning.com/seemann, mà làm giảm số lượng câu hỏi bạn sẽ tìm thấy khó hiểu trong kiến ​​trúc DI đáng kể - def chạy mua nó không có câu hỏi. –

Trả lời

12

Để có giải pháp với một ứng dụng duy nhất, lời khuyên chung là đăng ký vùng chứa của bạn trong dự án ứng dụng (ứng dụng web của bạn hoặc dự án dịch vụ web). Đối với một ứng dụng web, điều này thường là Global.asax Application_Start. Nơi bạn kết nối mọi thứ với nhau được gọi là Composition Root trong thuật ngữ DI.

Với giải pháp đa ứng dụng, bạn vẫn sẽ có một gốc thành phần duy nhất cho mỗi dự án ứng dụng. Điều này phải được, vì mọi ứng dụng đều có cấu hình duy nhất của nó. Mặt khác, mã trùng lặp luôn xấu. Bạn không muốn phải thay đổi ba nơi khi bạn giới thiệu một sự trừu tượng mới.

Bí quyết là di chuyển tất cả các đăng ký xuống phân cấp dự án. Ví dụ, bạn có thể định nghĩa một 'bootstrap assembly' duy nhất phụ thuộc vào các assembly nhóm nghiệp vụ của bạn (và bên dưới) và để nó có tất cả các đăng ký cho các assembly không thay đổi.Các thành phần rễ của các ứng dụng sau đó có thể sử dụng lắp ráp đó để có được đăng ký mặc định và mở rộng nó với các ứng dụng phụ thuộc cụ thể.

một điều như vậy có thể trông như thế này:

// MVC Composition root 
public static void Bootstrap() 
{ 
    var container = new Container(); 

    // Default registrations 
    BusinessLayerBootstrapper.Bootstrap(container); 

    // Application specific registrations 
    container.Bind<IUserContext>().To<AspNetUserContext>(); 

    DependencyResolver.Current = 
     new ContainerDependencyResolver(container); 
} 

// Windows Service Composition root 
public static void Bootstrap() 
{ 
    var container = new Container(); 

    // Default registrations 
    BusinessLayerBootstrapper.Bootstrap(container); 

    // Application specific registrations 
    container.Bind<IUserContext>().To<SystemUserContext>() 
     .SingleScoped(); 

    // Store somewhere. 
    Bootstrapper.Container = container; 
} 

// In the BL bootstrap assembly 
public static class BusinessLayerBootstrapper 
{ 
    public static void Bootstrap(Container container) 
    { 
     container.Bind<IDepenency>().To<RealThing>(); 
     // etc 
    } 
} 

Mặc dù bạn không cần phải có một hội đồng bootstrapper riêng biệt (bạn có thể đặt mã này trong BL chính nó), điều này cho phép bạn giữ cho doanh nghiệp của bạn lớp hội đồng miễn phí từ bất kỳ phụ thuộc vào container của bạn.

Cũng lưu ý rằng tôi chỉ đang gọi phương thức tĩnh Bootstrap(), thay vì sử dụng Mô-đun (Ninject). Tôi đã cố gắng giữ cho câu trả lời của mình không phụ thuộc vào khung làm việc, vì câu hỏi của bạn là chung và lời khuyên sẽ giống nhau cho tất cả các khuôn khổ DI. Tuy nhiên, tất nhiên bạn có thể sử dụng tính năng mô-đun Ninject nếu bạn muốn.

6

Về Phạm vi ứng dụng MVC cần phải có một CompositionRoot khác với một dịch vụ cửa sổ. Tôi đề nghị bạn cố gắng tổ chức càng nhiều càng tốt bởi các mô-đun tính năng (cho những phần đó là ứng dụng thuyết bất khả tri) và tất cả các ràng buộc khác trực tiếp trong compositionRoot của dự án MVC hoặc WindowsService.

Một cách tiếp cận rất tốt khác là xác định một tập hợp chung các quy ước giúp bạn thể hiện mối quan tâm ràng buộc nhất trong một vài dòng. Do đó ứng dụng của bạn có thể có những điều sau đây để bindings:

MVC App

Bind(c => c.FromAssemblyContaining<IRepository>() 
      .SelectAllClasses() 
      .InheritedFrom<IRepository>() 
      .Configure(b => b.InRequestScope())); 

dịch vụ Windows của bạn App

Bind(c => c.FromAssemblyContaining<IRepository>() 
      .SelectAllClasses() 
      .InheritedFrom<IRepository>() 
      .Configure(b => b.InThreadScope())); 

Trong quan điểm của tôi kết hợp với một tính năng định hướng cơ cấu phương pháp ước là sạch nhất.

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