简单注入器——从命名空间注册所有服务

10

我的服务接口的命名空间是Services.Interfaces

服务接口的实现具有Web.UI.Services的命名空间

举个例子,我有两个服务实现

  • IUserService需要注册到UserService
  • ICountryService需要注册到CountryService

这是我目前如何使用SimpleInjector注册这些服务的方法。

container.Register<IUserService, UserService> ();
container.Register<ICountryService, CountryService> ();
问题:如果我有超过100个服务(夸张一下),我需要去为每个服务添加一行。
如何使用Simple Injector将一个程序集中的所有实现注册到另一个程序集中的所有接口?
如何使用Simple Injector将一个程序集中的所有实现注册到另一个程序集中的所有接口?
2个回答

9
你可以通过使用LINQ和反射查询程序集并注册所有类型来实现此操作:
var registrations =
    from type in typeof(UserService).Assembly.GetExportedTypes()
    where type.Namespace.StartsWith("Services.Interfaces")
    where type.GetInterfaces().Any()
    select new { Service = type.GetInterfaces().Single(), Implementation = type };

foreach (var reg in registrations) {
    container.Register(reg.Service, reg.Implementation);
}

这里描述了此处

如果我有超过100个服务,夸张一点说。我需要为每个服务添加一行。

如果是这种情况,我认为你的设计存在问题。你称呼你的服务为IUserServiceICountryService表明你违反了单一职责原则(Single Responsibility)开闭原则(Open/closed)接口隔离原则(Interface Segregation Principles)。这可能会导致严重的可维护性问题。

如果您想尝试另一种设计,请查看这些 两篇文章。所描述的设计允许更高水平的可维护性,使注册服务变得更加容易,并且使用Simple Injector特别容易实现横切关注点。


3
Steven: 我很好奇,您如何从接口名称中判断OP违反了SRP、OCP原则?我并没有看出来。 - Sriram Sakthivel
Steven,谢谢你的回复。100个服务是夸张了。ICountryService和IUserService也完全没有关联。感谢你分享的文章,我会去仔细阅读的。 - Shane van Wyk
@ShiramSakthivel 阅读这篇文章,你就会明白了。这篇文章解释了这个问题。 - Steven
谢谢,我会研究一下的。 - Sriram Sakthivel
@Steven,看起来不是很好看。Simple Injector是否提供了更漂亮的方法,就像Autofac中的RegisterAssemblyTypes一样? - Neshta
1
@Neshta:Simple Injector专注于围绕SOLIDRAP原则设计的应用程序。这些类型的应用程序在接口和实现之间没有许多一对一的映射,这将(除其他事项外)最小化问题。我们选择专注于一种类型的API设计,而不是试图为所有类型的应用程序设计一个完美的API(这实际上非常困难),希望我们能够推动开发人员向SOLID设计方向发展。 - Steven

8
您正在寻找“约定优于配置”。Simple Injector 将其称为 批处理/自动注册
虽然大多数 DI 容器都提供了此功能的 API,但似乎 Simple Injector 让我们自己来完成;通过一些反射和 LINQ,可以将类型批量注册,因此 Simple Injector 并没有为此提供特殊的 API。
想法是扫描具有某些约定的程序集中的具体类型,查看它是否实现了任何接口;如果是,则注册它。
以下是从上述链接中提取的示例:
var repositoryAssembly = typeof(SqlUserRepository).Assembly;

var registrations =
    from type in repositoryAssembly.GetExportedTypes()
    where type.Namespace == "MyComp.MyProd.BL.SqlRepositories"
    where type.GetInterfaces().Any()
    select new { Service = type.GetInterfaces().Single(), Implementation = type };

foreach (var reg in registrations) {
    container.Register(reg.Service, reg.Implementation, Lifestyle.Transient);
} 

您可以修改此代码以批量应用您的约定并注册类型。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接