听起来像你是在我几年前的状态。
请注意,如果您需要更多帮助,我会向您发送一些代码。很难把所有的代码放在这里。
我试着解释我正在开发的项目中的当前体系结构。这篇文章有点冗长,但我想给你一个关于如何使用IOC在很多方面可以帮助你的大局。
所以我使用Ninject。在尝试使用Castle Windsor一段时间后,我发现Ninject易于启动和运行。 Ninject有一个很酷的网站,可以帮助你入门。
我所有的项目结构首先如下:(自上而下和它的MVC)
查看 - 剃刀 视图模型 - 我用按次1个视图模型
ViewModelBuilder - 为我的视图构建我的视图模型(用于将代码从我的控制器中抽离出来,以便控制器保持整洁)
AutoMapper - 域实体映射到我的视图模型
控制器 - 叫我的服务层来获得域实体
域实体 - 我的域名
ServiceLayer(业务交涉层) - 调用我的存储库层以获取域实体或这些的集合
AutoMapper再次 - 从我的第三方供应商映射自定义类型转换成我的域实体
RepositoryLayer - 确实CRUD操作我的数据存储
这是一个层次,但类型的域实体沿侧坐并用于几个不同的层。
注:在这篇文章中提到的一些额外的工具有:
AutoMapper - 地图实体到其他实体 - 无需编写映射代码
起订量负载 - 允许你嘲笑单元测试的东西。这在后面会提到。
现在,关于Ninject。
每层都标有接口。必须这样做,Ninject才能对自己说。
当我发现IVehicleRepository注入一个真正的VehicleRepository,甚至注入它与FakeVehicleRepository,如果我需要一个假的。
(这涉及到你的评论 - “这将让我的一切绑定到一个测试XML库”)
现在,每一层都有contstructor使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的。
如前所述,我可以将VehicleRepository替换为FakeVehicleRepository,这样我就不必从真实数据库中读取数据。
因此,正如你现在可以想象的那样,每一层只依赖于接口。
我不知道你做了多少单元测试,但你也可以想象,如果你想单元测试你的服务层,并且它具有对你的存储库层的具体引用,那么你将无法像你一样进行单元测试实际上打你的存储库,因此从一个真正的数据库中读取。
记住单元测试称为单元测试,因为它只测试一件事情。因此单词UNIT。所以,因为每个人都只知道接口,这意味着你可以在你的服务层上测试一个方法并模拟库。
所以,如果你的服务层具有这样的方法:
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给你。如果它实现了一个接口,你大多只能使用Mock的东西。
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容器都能让你以最少的痛苦快速运行。
我也会说,尝试和单元测试一切,你可以。这有很多不同的原因。很明显,它会测试你编写的代码,但它也会立即告诉你,如果你做了一些愚蠢的事情,比如新建一个具体的存储库。你会很快看到你不会有一个接口来模拟你的单元测试,这将导致你回去重构你的代码。
我发现使用IOC,需要一段时间才能得到它。它把你的垃圾混淆直到有一天它只是点击。在那之后,你很容易想到你如何在没有它的情况下生活。
这里的东西我不能生活在没有 Automapper 起订量 流利验证 ReSharper的清单 - 有些恨它,我喜欢它,主要是它的单元测试UI。
无论如何,这是太长了。让我知道你的想法。
感谢 拉斯
我只是删除一切,并试图再次统一,因为这是我来最接近的一次。在预感上,我删除了一个构造函数,它带有参数,我认为它工作。我不知道为什么当空的构造函数可用时它锁定在构造函数上(我所做的只是评论其他)。明天早上将继续关注此事。 – 2013-02-12 21:48:29