我已经阅读或尝试阅读过多的“操作方法”,却一无所获。统一? System.Web.Http.Dependencies? Ninject? StructureMap?啊。我只想要一些简单的可行的方法!我只是不知道它的当前状态是什么。有很多不同的方法,示例似乎并不完整。最好的线索有一个示例项目,我无法在VS2010或2012中加载。我浪费了一天3/4的时间,我觉得本该最多应该花半个小时才能继续前进!只是水暖!
我有一个基于泛型的存储库来处理许多都支持相同操作的数据集。
知识库
我想控制每个数据集绑定(bind)到哪个存储库。这将使我可以将所有内容绑定(bind)到测试XML存储库,并随着项目的进行将它们过渡到SQL存储库。
我一定会很乐意为您提供帮助!谢谢!
最佳答案
听起来像您是几年前的状态。
请注意,如果您需要其他帮助,我会向您发送一些代码。很难将所有代码放在这里。
我将尝试解释我正在研究的项目中的当前体系结构。这篇文章有些冗长,但我想向您全面介绍如何使用IOC可以在许多方面为您提供帮助。
所以我用Ninject。尝试使用温莎城堡一段时间后,我发现Ninject易于安装和运行。 Ninject有一个不错的网站,它将帮助您入门。
首先,我的项目结构如下:(自上而下,它是MVC)
查看-剃刀
ViewModel -我为每个 View 使用1个 View 模型
ViewModelBuilder -为我的 View 构建我的 View 模型(用于将代码抽象到我的 Controller 之外,以便我的 Controller 保持整洁)
AutoMapper -将域实体映射到我的 View 模型
Controller -调用我的服务层以获取域实体
域实体-我的域的表示形式
ServiceLayer(业务层)-调用我的存储库层以获取域实体或这些实体的集合
AutoMapper再次-将来自第三方供应商的自定义类型映射到我的域实体中
RepositoryLayer -对我的数据存储区执行CRUD操作
这是一个层次结构,但Domain实体位于旁边,并在几个不同的层中使用。
注意:本文中提到的一些额外工具是:
AutoMapper -将实体映射到其他实体-无需编写大量映射代码
Moq -允许您模拟东西进行单元测试。稍后会提到。
现在,关于Ninject。
每层都标有一个接口(interface)。必须这样做,Ninject才能对自己说。
当我找到IVehicleRepository时,将其注入真实的VehicleRepository,或者如果我需要假的,甚至将其注入FakeVehicleRepository。
(这与您的评论有关-“这将使我可以将所有内容绑定(bind)到测试XML存储库”)
现在,每个层都有一个构造函数,因此Ninject(或任何其他IOC容器)可以注入所需的内容:
public VehicleManager(IVehicleRepository vehicleRepository)
{
this._vehicleRepository = vehicleRepository;
}
VehicleManager在我的serviceLayer中(不要与与Web服务有关的任何东西混淆)。服务层实际上就是我们所说的业务层。似乎很多人都在使用服务一词。 (尽管我认为这很烦人,因为它使我考虑使用Web服务或WCF而不是仅仅考虑业务层...。无论如何...)
现在,无需深入了解Ninject设置,我的NinjectWebCommon.cs中的以下代码行告诉ninject该做什么:
kernel.Bind<IVehicleRepository>().To<VehicleRepository>().InRequestScope();
这说:
嘿Ninject,当我要求IVehicleRepository时,请给我一个具体的VehicleRepository实现。
如前所述,我可以用FakeVehicleRepository替换VehicleRepository,这样我就不必从真实的数据库中读取内容。
因此,正如您现在可以想象的那样,每一层仅依赖于接口(interface)。
我不知道您已经进行了多少单元测试,但是您也可以想象,如果您想对服务层进行单元测试,并且它对存储层有具体的引用,那么您将无法进行单元测试,因为您实际上会遇到问题。存储库,并因此从真实数据库中读取。
请记住,单元测试称为单元测试,因为它仅测试一项。因此,单词UNIT。因此,因为一切都只知道接口(interface),所以这意味着您可以在服务层上测试方法并模拟存储库。
因此,如果您的服务层具有如下方法:
public bool ThisIsACar(int id)
{
bool isCar = false;
var vehicle = vehicleRepository.GetVehicleById(id);
if(vehicle.Type == VehicleType.Car)
{
isCar = true;
}
else
{
isCar = false;
}
}
您不希望调用vehicleRepository,所以可以按最小要求VehicleRepository退还给您的内容。如果实现了接口(interface),则大多数情况下只能模拟它们。
So your unit test would look like this (some pseudo code here):
[TestMethod]
public void ServiceMethodThisIsACar_Returns_True_When_VehicleIsACar()
{
// Arrange
_mockRepository.Setup(x => x.ThisIsACar(It.IsAny<int>)).returns(new Car with a type of VehicleType.Car)
// Act
var vehicleManager = new VehicleManager(_mockVehicleRepository.Object);
var vehicle = vehicleManager.ThisIsACar(3);
// Assert
Assert.IsTrue(vehicle.VehicleType == VehicleType.Car)
}
如您所见,在这一点上,它已经非常简化,您只想在服务层中测试IF语句,以确保结果正确。
您将在自己的单元测试中测试存储库,并可能在使用实体框架时对其进行模拟。
因此,总的来说,我会使用任何IOC容器来使您起步并以最少的痛苦运行得最快。
我还要说,尽力对单元进行测试。出于几个不同的原因,这很不错。显然,它可以测试您编写的代码,但是如果您做过一些愚蠢的事情(例如新建一个具体的存储库),它也会立即向您显示。您很快就会发现,在单元测试中没有模拟接口(interface),这将使您返回并重构代码。
我发现使用IOC会花一些时间。直到有一天它单击时,它会使您感到困惑。之后,它是如此的容易,您想知道没有它的生活。
这是我不能没有的生活清单
自动映射器
起订量
流利验证
Resharper-我非常讨厌它,主要是因为其单元测试UI。
无论如何,这太长了。让我知道你的想法。
谢谢
俄罗斯
关于asp.net-web-api - 如何为MVC4/VS2012/Web API注入(inject) Controller ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14842061/