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

Sha*_*Wyk 10 c# asp.net-mvc ioc-container inversion-of-control simple-injector

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

Service Interfaces的实现具有名称空间 Web.UI.Services

例如,我有2个服务实现

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

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

container.Register<IUserService, UserService> ();
container.Register<ICountryService, CountryService> ();
Run Code Online (Sandbox Code Playgroud)

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

如何使用Simple Injector将所有实现从一个程序集注册到所有接口形成另一个程序集?

Ste*_*ven 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);
}
Run Code Online (Sandbox Code Playgroud)

在这里描述.

如果我有超过100个服务夸大一点.我需要为每项服务添加一行.

如果是这种情况,我认为你的设计有问题.你打电话给你的服务的事实IUserService,并ICountryService为您违反了指示单一责任,开/关接口分离原则.这可能会导致严重的可维护性问题.

对于替代设计,请查看 两篇文章.所描述的设计允许更高水平的可维护性,使注册服务变得更加容易,并且使得孩子们应用横切关注点(特别是使用Simple Injector).

  • 史蒂文:我很好奇,你怎么能说OP从界面名称中侵犯了SRP,OCP?我没有看到. (3认同)

Sri*_*vel 8

您正在寻找"约定优于配置".简单的进样器调用此批处理/自动注册.

虽然主要的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);
} 
Run Code Online (Sandbox Code Playgroud)

您可以修改此代码以批量应用约定和寄存器类型.