Внимание! Это краткий перевод вопроса Implement dependency injection outside of Startup.cs
Есть проект asp.net core со множеством репозиториев и сервисов, в файле Startup.cs огромная нечитаемая портянка регистрации:
services.AddTransient<IContactRepository, ContactRepository>();
services.AddTransient<ICityRepository, CityRepository>();
//..... and so on
services.AddTransient<ICityService, CityService>();
services.AddTransient<IContactServiceBase, ContactServiceBase>();
//..... and so on
Можно ли каким-то образом зарегистрировать все эти зависимости более коротким способом?
Подобные вещи в англоязычной литературе называются batch registration, иногда применяется ещё термин assembly scanning.
В asp.net core есть возможность заменить встроенный DI на autofac, который умеет сканировать сборки и регистрировать типы:
var assembly = Assembly.GetExecutingAssembly();
builder.RegisterAssemblyTypes(assembly)
.Where(t => t.Name.EndsWith("Repository"))
.AsImplementedInterfaces();
А встроенный DI (до сих пор - даже в core 2.1) не поддерживает сканирование сборок :(
Однако вы можете воспользоваться проектом Scrutor: установив его из nuget вы сможете регистрировать зависимости следующим образом:
var collection = new ServiceCollection();
collection.Scan(scan => scan
.FromAssemblyOf<ITransientService>()
.AddClasses(classes => classes.AssignableTo<ITransientService>())
.AsImplementedInterfaces()
.WithTransientLifetime()
.AddClasses(classes => classes.AssignableTo<IScopedService>())
.As<IScopedService>()
.WithScopedLifetime());
Если вы не хотите подключать дополнительные пакеты, то можете написать небольшой экстеншн:
public static void AddScopedFromAssembly(this IServiceCollection services, Assembly assembly)
{
var allServices = assembly.GetTypes().Where(p =>
p.GetTypeInfo().IsClass &&
!p.GetTypeInfo().IsAbstract);
foreach (var type in allServices)
{
var allInterfaces = type.GetInterfaces();
var mainInterfaces = allInterfaces.Except
(allInterfaces.SelectMany(t => t.GetInterfaces()));
foreach (var itype in mainInterfaces)
{
services.AddScoped(itype, type); // if you want you can pass lifetime as a parameter
}
}
}
Использовать так:
services.AddScopedFromAssembly(assembly);
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Есть проектНачальство, спустя более 40к строк кода решило добавить логирование
Возникла проблема с WPF: в приложении у меня при нажатии кнопки должен открыться файл с расширениемxlsx и его содержимое перенестись в DataGrid,...