我现在对DI和IoC容器有了很好的理解,但我不确定如何处理在多个“模块”(DLL,无论如何)中有几十个类的真实世界方面。几乎所有我见过的IoC示例都使用了一些类,并在Main方法中手动设置容器(如果是web应用程序,则为Global.asax),这对于大型应用程序来说是疯狂的有数百行只使用For<I>().Use<T>()
语法来设置所有内容。
我做了一些研究,这似乎是注册表(StructureMap)和内核(Ninject)类的目的(那些是我熟悉的两个IoC容器,因此它们在这里提到 - 我确定其他IoC容器有类似的东西。
现在,我的问题是你打算创建一个不同的注册表(我一直在使用StructureMap,所以我会坚持使用这个术语),它对应于应用程序中的每个分组(例如存储库,实体,服务)让我们说一个“基础设施”类库,然后在主应用程序入口点连接这些类?我想你可以更进一步,为每个聚合创建一个注册表(使用DDD术语),然后将所有这些注册表连接到包含应用程序整个部分的更广泛的注册表类中(例如,更大的LOB应用程序的CRM部分)可能有几个聚合本身,所以你有一个注册表连接每个聚合,然后一个更大的注册表,结合所有聚合注册表..我希望这是有道理的!)
基本示例:
// MyApp.Infrastructure
class ServiceRegistry : Registry
{
public ServiceRegistry()
{
For<IOrderService>().Use<OrderService>();
// other services...
}
}
class RepositoryRegistry: Registry
{
public RepositoryRegistry()
{
For<IOrderRepository>().Use<OrderRepository>();
// other repositories...
}
}
// other registry files e.g. for Entities
// Global.asax or Program.cs or whatever entry point
ObjectFactory.Initialize(x => {
x.AddRegistry<ServiceRegistry>();
x.AddRegistry<RepositoryRegistry>();
// other registries
});
这是处理真实应用程序的首选方式,这些应用程序可能有数十个(如果不是数百个)逻辑组织的类吗?
答案 0 :(得分:4)
对于像这样的大型项目,您可能希望偏好约定优于配置。例如,StructureMap具有默认的常规扫描程序,或者您可以编写自定义扫描程序。看看这里:http://codebetter.com/jeremymiller/2009/01/20/create-your-own-auto-registration-convention-with-structuremap/
所以,假设您通常使用构造函数注入,并且您的IoC引导程序可以看到给定程序集中接口的一个实现,您只需将其设置为扫描该程序集,它将自动连接构造函数依赖项。 / p>
答案 1 :(得分:1)
在StructureMap中,已经提供了注册表聚合器。 在scanning assemblies上查看StructureMap的文档。 您应该为每个程序集创建一个注册表(您可以在一个程序集中执行多个,但没有任何明显的好处)。
然后,您可以使用扫描功能查找所有注册表。您还需要使用注册约定(在Scan()
子句中),这样您就不必显式注册每个实现。
ObjectFactory.Initialize(x => {
x.Scan(s => {
// Add the current assembly
s.TheCallingAssembly();
// Add all assembly from a specified path
s.AssembliesFromPath("Extensions");
// Automatically look and execute registries
s.LookForRegistries();
// specify some conventions
s.WithDefaultConventions();
});
});
答案 2 :(得分:0)
当我使用Spring时,我有逐层的单独配置文件(Web,服务,持久性等)。与所有分层技术一样,这些技术可以将逻辑上的配置保存在一个可以使关系清晰的位置。
所有计算机科学都有这样的共同点:通过将其分解为更小,更易于管理的块来处理复杂性。
答案 3 :(得分:0)
即使是名称注册表也可能令人困惑,尽管它来自Fowlers的“企业应用程序设计模式”一书。您可以考虑将入口点称为应用程序的组合根(请参阅Marc Seemans .NET Dependency Injection,manning book)。 无论如何,你应该为每个应用程序都有一个组合根,不要在应用程序之间共享组合根,因为它们将接口与它们联系起来,而某些应用程序可能不需要你所有的接口。
希望有道理:)
答案 4 :(得分:0)
您可能希望使用IoC的“自动装配”功能。例如如果您将接口的实现分离到不同的程序集并且只分发一个版本,那么IoC-Container将能够自动找到合适的实现,并且您不必手动告诉容器在解析时应该使用哪个实现。依赖性。
在Spring.Net和StructureMaps中称为“自动装配”(byType,byName,...)。