10

在MVC3應用程序與Ninject.MVC 2.2.0.3(after merge),而不是直接向控制器注入repostories我試圖做一個服務層包含businesslogic並注入在那裏的倉庫。我將ninject-DependencyResolver作爲動態對象傳遞給服務層(因爲我不想引用mvc或ninject)。然後我調用GetService來獲取存儲庫,並使用我在NinjectHttpApplicationModule中指定的綁定和生命週期。編輯:總之,它失敗了。Ninject.MVC3,將DependencyResolver傳遞給服務層?

在這種情況下,IoC容器如何傳遞給服務層? (不同的方法也非常受歡迎。)

編輯:下面是一個例子來說明我如何理解答案和評論。

我應該避免服務定位器(anti-)pattern,而是使用依賴注入。因此,可以說我想爲Northwind的產品和類別創建一個管理站點。根據表定義創建模型,存儲庫,服務,控制器和視圖。這些服務直接調用存儲庫,在那裏沒有邏輯。我有支柱功能和視圖顯示原始數據。通過構造注入兩層

private static void RegisterServices(IKernel kernel) 
    { 
     kernel.Bind<ICategoryRepository>().To<CategoryRepository>(); 
     kernel.Bind<IProductRepository>().To<ProductRepository>(); 
    }  

庫-實例由ninject創建,在ProductController的:這些綁定被配置用於NinjectMVC3

private readonly ProductsService _productsService; 
public ProductController(ProductsService productsService) 
{ 
    // Trimmed for this post: nullchecks with throw ArgumentNullException 
    _productsService = productsService; 
} 

和ProductsService:

protected readonly IProductRepository _productRepository; 
public ProductsService(IProductRepository productRepository) 
{ 
    _productRepository = productRepository; 
} 

我現在不需要分離服務,但已經準備好模擬分貝。
要顯示在產品/編輯類別的下拉我讓持有的類別,除了產品一個ViewModel:

public class ProductViewModel 
{ 
    public Product Product { get; set; } 
    public IEnumerable<Category> Categories { get; set; } 
} 

的ProductsService現在需要一個CategoriesRepository創建它。

private readonly ICategoryRepository _categoryRepository; 

    // Changed constructor to take the additional repository 
    public ProductsServiceEx(IProductRepository productRepository, 
     ICategoryRepository categoryRepository) 
    { 
     _productRepository = productRepository; 
     _categoryRepository = categoryRepository; 
    } 

    public ProductViewModel GetProductViewModel(int id) 
    { 
     return new ProductViewModel 
        { 
         Product = _productRepository.GetById(id), 
         Categories = _categoryRepository.GetAll().ToArray(), 
        }; 
    } 

我改變GET編輯-行動return View(_productsService.GetProductViewModel(id));和編輯視圖顯示一個下拉菜單:

@model Northwind.BLL.ProductViewModel 
... 
    @Html.DropDownListFor(pvm => pvm.Product.CategoryId, Model.Categories 
     .Select(c => new SelectListItem{Text = c.Name, Value = c.Id.ToString(), Selected = c.Id == Model.Product.CategoryId})) 

一個小問題這一點,和我之所以與服務定位誤入歧途是否ProductController中的其他操作方法都不需要categories-repository。除非需要,否則我覺得創建它是浪費和不合邏輯的。我錯過了什麼嗎?

+1

相關:http://stackoverflow.com/questions/2386487/is-it-better-to-create-a-singleton -to-access-unity-container-or-pass-it-through-t – 2011-03-01 08:46:11

+0

謝謝。我沒有意識到我描述了服務定位器。 – Grastveit 2011-03-01 23:49:30

回答

14

你並不需要傳遞的對象周圍,你可以做這樣的事情

// global.aspx


protected void Application_Start() 
     { 
      // Hook our DI stuff when application starts 
      SetupDependencyInjection(); 
     } 

     public void SetupDependencyInjection() 
     {   
      // Tell ASP.NET MVC 3 to use our Ninject DI Container 
      DependencyResolver.SetResolver(new NinjectDependencyResolver(CreateKernel())); 
     } 

     protected IKernel CreateKernel() 
     { 
      var modules = new INinjectModule[] 
           { 
           new NhibernateModule(), 
           new ServiceModule(), 
           new RepoModule() 
           }; 

      return new StandardKernel(modules); 
     } 

所以在這一塊我設置的所有ninject東西。我用3個文件創建一個核心,將所有的綁定分開,這樣很容易找到。


在我的服務層類中,您只需傳入所需的接口。此服務類位於其自己的項目文件夾中,我保留了所有服務圖層類,並且沒有對ninject庫的引用。

// service.cs

private readonly IRepo repo; 
    // constructor 
     public Service(IRepo repo) 
     { 
      this.repo = repo; 
     } 

這是我ServiceModule看起來像(什麼是在global.aspx創建)

// ServiceModule() 
public class ServiceModule : NinjectModule 
    { 
     public override void Load() 
     { 

      Bind<IRepo>().To<Repo>(); 


     } 

    }  

SEEE我怎麼綁定接口回購。現在,每次看到該界面時,它都會自動將Repo類綁定到它。所以你不需要傳遞對象或任何東西。

您不需要擔心導入.dll到您的服務層。例如,我在自己的項目文件中有我的服務類,上面看到的所有東西(期望服務類當然)都在我的webui項目(我的views和global.aspx)中。

Ninject不關心該服務是否在不同的項目中,因爲我猜它是在webui項目中引用的。

編輯

忘了給你的NinjectDependecyResolver

public class NinjectDependencyResolver : IDependencyResolver 
    { 
     private readonly IResolutionRoot resolutionRoot; 

     public NinjectDependencyResolver(IResolutionRoot kernel) 
     { 
      resolutionRoot = kernel; 
     } 

     public object GetService(Type serviceType) 
     { 
      return resolutionRoot.TryGet(serviceType); 
     } 

     public IEnumerable<object> GetServices(Type serviceType) 
     { 
      return resolutionRoot.GetAll(serviceType); 
     } 
    } 
+0

構造函數注入+1和MVC DependencyResolver。 – 2011-03-01 00:01:47

+0

非常全面的答案!因此,不要在服務內部隨意創建存儲庫,要麼確保服務中的所有方法使用相同的存儲庫,要麼不必擔心創建不需要的存儲庫? – Grastveit 2011-03-01 00:38:50

+0

請不要使用此答案中的自定義DependencyResolver和Application_Start。留在Ninject.MVC3!如上所述,只需實現構造器注入。如上所述,不需要使用Ninject作爲服務定位器。 – 2011-03-01 01:08:30