在具有 Ninject.MVC 2.2.0.3 (合并后)的 MVC3 应用程序中,我没有将存储库直接注入控制器,而是尝试创建一个包含业务逻辑的服务层并在那里注入存储库。我将 ninject-DependencyResolver 作为动态对象传递给服务层(因为我不想在那里引用 mvc 或 ninject)。然后我在其上调用 GetService 以获取具有我在 NinjectHttpApplicationModule 中指定的绑定和生命周期的存储库。编辑:简而言之,它失败了。
在这种情况下,如何将 IoC 容器传递给服务层?(也非常欢迎不同的方法。)
编辑:这是一个例子来说明我如何理解答案和评论。
我应该避免使用服务定位器(反)模式,而是使用依赖注入。因此,假设我想在 Northwind 中为产品和类别创建一个管理站点。我根据表定义创建模型、存储库、服务、控制器和视图。此时服务直接调用存储库,没有逻辑。我有功能支柱,视图显示原始数据。这些绑定是为 NinjectMVC3 配置的:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ICategoryRepository>().To<CategoryRepository>();
kernel.Bind<IProductRepository>().To<ProductRepository>();
}
存储库实例由 ninject 通过两层构造函数注入在 ProductController 中创建:
private readonly ProductsService _productsService;
public ProductController(ProductsService productsService)
{
// Trimmed for this post: nullchecks with throw ArgumentNullException
_productsService = productsService;
}
和产品服务:
protected readonly IProductRepository _productRepository;
public ProductsService(IProductRepository productRepository)
{
_productRepository = productRepository;
}
我现在不需要解耦服务,但已经准备好模拟数据库了。
为了在 Product/Edit 中显示类别的下拉列表,我创建了一个 ViewModel,其中包含除 Product 之外的类别:
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 Edit-action 更改为return View(_productsService.GetProductViewModel(id));
和 Edit-view 以显示下拉列表:
@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}))
一个小问题,也是我在 Service Locator 上误入歧途的原因,是 ProductController 中的其他操作方法都不需要类别存储库。我觉得除非需要,否则创建它是一种浪费且不合逻辑。我错过了什么吗?