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

Simple Injector Register All Services From Namespace

我的服务接口有一个命名空间Services.Interfaces

服务接口的实现具有 Web.UI.Services

的命名空间

例如,我有 2 个服务实现

这就是我目前使用 SimpleInjector 注册这些服务的方式。

container.Register<IUserService, UserService> ();
container.Register<ICountryService, CountryService> ();

问题:如果我有超过 100 个服务就夸大了一点。我需要去为每个服务添加一行。

如何使用简单注入器将一个程序集中的所有实现注册到另一个程序集中的所有接口?

您正在寻找 "Convention over configuration"。简单的注入器调用这个 Batch / Automatic registration.

虽然主要的 DI 容器为此提供了 API,但似乎 Simple Injector 留给了我们;通过一些反射和 LINQ,可以将类型注册为批处理,因此 Simple Injector 没有为此提供特殊的 API。

想法是您按照某种约定扫描程序集以查找具体类型,查看它是否实现了任何接口;如果是,则注册它。

这是从上面提取的样本 link:

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);
} 

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

您可以通过使用 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);
}

这是描述here

If I have over 100 services to exaggerate a bit. I need to go and add a line for each service.

如果是这种情况,我认为您的设计有问题。您调用服务 IUserServiceICountryService 这一事实表明您违反了 Single Responsibility, Open/closed and Interface Segregation Principles。这会导致严重的可维护性问题。

对于替代设计,请查看 these two 文章。所描述的设计允许更高级别的可维护性,更容易注册您的服务,并使应用横切关注点变得简单(尤其是使用 Simple Injector)。