我正在阅读Mark Seemann的“.NET中的依赖注入”。我想知道组成DDD ASP.NET MVC应用程序的最佳方法是什么。
在简化的场景中,一般的经验法则是将域模型作为应用程序的核心,并且不会对数据层或表示有任何依赖性。它将暴露Presentation将使用的某些接口(因此依赖)和数据层将实现(因此依赖)。所以这一切都很好而且清晰。
然而,现在,当我们撰写应用程序时。对于ASP.NET MVC应用程序,我们将在global.asax(http://blog.ploeh.dk/2011/07/28/CompositionRoot)中进行。我们的组合根将需要依赖所有层,因为它需要注册所有适用的类型。
这使得所有依赖项看起来都很混乱,现在Presentation层有一个对数据访问层的项目引用(在VS术语中)。开发人员很容易犯错并直接使用数据形式的数据访问层,这将有效地耦合这些层。
有解决这个难题的干净方法吗?将Composition Root放在表示层之外几乎是很好的,但在MVC中是不可能的。
更新
在问这个问题后,我发现了一个相关的问题: DAL -> BLL <- GUI + composition root. How to setup DI-bindings? 它有一些有意义的解决方案。接受的解决方案几乎是完美的,但我希望组合根在表示层之外,并且参考表示层而不是其他方式。
这样做的一个原因是,对我来说概念更清晰 - 构图应该在最顶层。另一个原因是在我的情况下,表示层中已经有许多DI对象(主要是查看模型映射器的域对象),我想将它们组合在一个位置。
这个帖子给了我一些想法,我认为我想做的事情可能是可能的。
答案 0 :(得分:3)
开发人员很容易犯错并直接使用数据形式的数据访问层,这将有效地耦合这些层。
无论你如何阻止它,很容易做很多愚蠢的事情。不要在开发人员不做之后为您的应用程序建模。对它进行建模,以便正确地完成任务。
他接受的解决方案几乎是完美的,但是我想要的 组合根要在表示层之外,并且引用 表示层而不是其他方式。
我的容器支持您的要求。在每个项目中创建一个模块,用于注册其他所有内容:
public class CompositionRoot : IContainerModule
{
public void Register(IContainerRegistrar registrar)
{
registrar.RegisterType<ISomeType, SomeType>();
}
}
在您的UI项目中,您只需加载所有dll:
registrar.RegisterModules(Lifetime.Scoped,
Environment.CurrentDirectory,
"myproject.*.dll");
就是这样(如果使用[Component]
属性标记实现,也可以用一行替换大多数手动RegisterType等。)
答案 1 :(得分:2)
大多数IoC容器都暴露了将绑定逻辑分组到模块中的概念。
结果是只有包含模块的程序集需要知道具体的实现,而组合根只需要访问模块。
示例(伪):
// In data access assembly
namespace MyProject.DataAccessLayer
{
internal class MyRepository : IMyRepository
{
// ...
}
public class DataAccessModule : IModule
{
void Configure(container)
{
container.ForInterface<IMyRepository>()
.UseType<MyReposutiry>()
.Singleton();
}
}
}
// In presentation layer assembly
namespace MyWebApp
{
void Booptstrap()
{
var iocContainer = /* ... */
iocContainer.AddModule(new RepositoryModule());
}
}
请注意,MyRepository的具体实现类是 internal 。只有模块需要看到它。
此模式的自然扩展是每个程序集公开公开仅 IoC模块,所有其他具体类都是内部实现细节。
答案 2 :(得分:1)
获得更高程度的封装的一种方法是将域公开为HTTP服务,比如ASP.NET WebAPI。然后,ASP.NET MVC解决方案将引用此API。没有数据访问依赖性,只有对服务的引用。为简单起见,可以将API的已发布语言提取到可由MVC表示解决方案引用的程序集中。这种方法的权衡是添加移动部件以及创建和管理服务所涉及的步骤。
此外,拥有您描述的配置是完全可以接受的。通过提取服务获得的封装可能不值这个价格。开发人员应该有纪律来防止您描述的那种泄漏。
答案 3 :(得分:0)
我正在研究以上述eulerfx描述的方式构建的解决方案(这是系统要求而不是我自己的设计选择)。它可以解决您的问题,但您可能需要考虑将域模型类与域分离。此外,您将需要另一个用于web api服务的组合根,并且正如他所指出的,从webcontroller视图模型(必须在服务和网站之间共享)到域模型的另一层映射。
我现在使用.NET中的依赖注入书中描述的方法创建了一些解决方案,我可以说使用其中描述的方法肯定意味着质量更好,松散耦合的代码。
祝你好运!