使用依赖注入组织ASP.Net MVC解决方案的最佳方法是什么?

时间:2009-06-08 01:25:01

标签: asp.net-mvc dependency-injection inversion-of-control structuremap

我很早就开发了一个新的ASP.Net MVC项目,我使用这个项目进入DI。我很确定我会选择结构图,但这不是我要问的问题。我想弄清楚的是如何最好地组织我的解决方案。单元测试项目和模型都可以获取配置文件来映射它们的依赖关系,还是有一个类来统治它们?

另外,在我走得太远之前,还有什么新手陷阱要避免吗?

非常感谢,全部......

更新 我应该补充一点,当我说“组织解决方案”时,我不是指文件/文件夹的数量等,而是如何构建与DI有关的类。特别是,如何管理引导程序。我可以看到我的言语不好会导致混淆。

3 个答案:

答案 0 :(得分:11)

如果你是唯一一个参与该项目的人,我会先做对你有意义的事情。没有比你发现不直观的目录或项目结构更糟糕的事情。 BaseController类是\ Core \文件夹还是\ Controller \文件夹?我亲自看看控制器,但有些人发誓它应该在\ Core \或\ Bases。

第一个新手陷阱认为您可以以错误的方式组织您的代码,并以某种方式反映项目的成功。我见过有30个文件放在一个文件夹中的项目和其他有30个文件夹有20个文件夹的项目。

第二个新手陷阱忘记了与其他语言相比,您可以获得令人敬畏的智能感知,代码导航工具和Visual Studio的重构支持。你还有一个编译器,它使错误放置文件远没那么痛苦。如果你把某些东西放在“错误”的位置,那么你可以随时找到它并将它拖到需要的地方。

我说实话我现在正在开展一个项目,我甚至不确定某些类在我的文件结构中的位置。转到定义/声明是我经常使用的键盘快捷键。因为只有我使用代码这很好。如果我不得不在项目中添加另一个开发人员,我可能会把事情搞清楚。

我个人倾向于将Interfaces的实现类型放在同一个文件夹中。 IPaymentGateway与AuthorizeNetGateway和PaypalGateway位于同一文件夹中。如果我无法在解决方案资源管理器侧栏中一次查看该文件夹中的所有文件,那么我将所有网关文件移动到\ Gateway \文件夹中。

随着依赖注入添加到混合中,我建议你只关注命名空间爆炸。你可以做的最糟糕的事情是使用声明和别名长时间搞乱你的bootstrappers和文件。

ForRequestedType<Customer>

更清洁
using KevDog.Models
using Customer=KevDog.Models.Customer

ForRequestedType<KevDog.Models.Customer>

避免此问题的另一种方法是在命名时明确:Customer,CustomerViewModel,CustomerController,CustomerDataRow,CustomerView

对于TDD,您几乎必须有两个bootstrappers来管理您的具体类型。你真的不希望你的单元测试使用AuthorizeNetGateway:IPaymentGateway,而不是StubGateway:IPaymentGateway。

现在我也是DI的新手,所以我倾向于使事情变得非常简单并反映101级教程和文档。只有在特定情况需要时才能使用基于构建配置的动态注入,并且您确切知道为什么要这样做。

我通常也会保留MVC应用程序的默认结构。它的代码与99%的教程和视频相同,更容易。

希望这有帮助。

答案 1 :(得分:2)

鼓励更好的TDD。有两个测试项目和/或名称X.Unit.Tests&amp; X.Integrations.Tests。

我的主项目中的DI代码位于“命名空间目录”(/ Config)中,但在我的集成代码测试中,我可能只是调用这些注册表或覆盖我在基本灯具或设置中的要求。

E.g。

/Config/ServiceRegistry.cs /Config/RepositoryRegistry.cs /Config/Bootstrapper.cs

在global.asax中,我调用Bootstrapper.Init(),这将调用x.AddRegistry(new ServiceRegistry()),依此类推。

在我的单元测试中,您不需要仅在集成测试中使用DI。在我的IntegrationTests中,例如如果我正在测试NHibernate到数据库,我可能会在TestSetUp中使用RepositoryRegistry初始化SM,并使用帮助器方法包装GetInstance()。

我没有拆分到项目.Bootstraper和.Domain,直到我必须...三个项目,X,X.UnitTests,X.Integration如果你以后需要更多的移动。我来自一个背景/公司强制执行有几十个项目,它感觉很脏,第一次减少但不是现在,如果需要,我会快速地进行快速增长并重新组织解决方案结构。

答案 2 :(得分:0)

这是我第一次尝试为自己解决同样的问题,但由于这是我的第一次尝试,我希望人们可以评论或评论它,因为我希望它可以作为你的一个可能的解决方案:

public VatManager()
 : this(new VatManagerRegistry()) { }

public VatManager(Registry registry)
 : this(new Action<IInitializationExpression>(x => { x.AddRegistry(registry); }))
  {
  }

public VatManager(Action<IInitializationExpression> action)
  {
   ObjectFactory.Initialize(action);
   data = ObjectFactory.GetInstance<IVatManagerData>();
  }

我有三个构造函数重载 - 无参数默认构造函数知道需要创建用于生产上下文的具体StructureMap注册表。另外两个允许实例化此管理器类的其他代码提供它们自己的StructureMap注册表或动作,以便它们可以自己控制依赖注入,例如在自动化测试的情况下提供模拟而不是那些具体实例依赖。 我应该补充一点,这个解决方案并不特定于ASP.NET MVC上下文,也不会从* .config文件中提取任何配置信息。