Как автоматически добавить регистрацию моей службы в контейнер di

Я хочу автоматизировать добавление сервисов в контейнер di. Здесь, в моем классе ServiceRegistration:

builder.Services.AddScoped<ICategoryService, CategoryService>();
builder.Services.AddScoped<IProductDetailService, ProductDetailService>();
builder.Services.AddScoped<IProductImageService, ProductImageService>();
builder.Services.AddScoped<IProductService, ProductService>();
...

Я не хочу добавлять подобное, я хочу пометить каждый из моих классов обслуживания атрибутом, найти этот класс, найти интерфейс, который реализует найденный мной класс, и автоматически добавить его в контейнер di. Как мне это сделать? Или у вас есть лучшее решение?

Я не хочу добавлять свои услуги вручную, я хочу делать это автоматически

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
75
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете использовать отражение:

var components =
    from type in typeof(CategoryService).Assembly.GetTypes()
    where type.Name.EndsWith("Service")
    where !type.IsAbstract && !type.IsGenenicTypeDefinition
    where type.GetInterfaces().Count() == 1
    select { Service = type.GetInterfaces().Single(), Implementation = type };

foreach (var component in components)
{
    services.AddScoped(component.Service, component.Implementation);
}

Также доступны расширения для MS.DI, которые могут упростить эту задачу, например Scrutor.

спасибо большое, мой Стивен. У меня есть еще один вопрос; не будет ли мне здесь дорого стоить использование отражения? Было бы правильно вместо этого создать SourceGenerator? Я создал генератор исходного кода, но он не дает необходимого ответа во время компиляции. Спасибо за ваш ответ.

JacksonT 04.06.2024 14:25

«Разве использование отражения не обойдется мне здесь дорого?» Много чего?

Steven 04.06.2024 14:59

Мне нужно использовать его в большом проекте. Не приводит ли отражение к уязвимостям безопасности, проблемам с производительностью и увеличению использования памяти? Генерация кода статически во время компиляции с помощью генератора исходного кода показалась мне более предпочтительной, но мне хотелось бы узнать ваше мнение.

JacksonT 04.06.2024 15:25

«Не является ли отражение причиной уязвимостей безопасности» — Нет, это не так.

Steven 04.06.2024 15:50

«Проблемы с производительностью». Вам придется измерить это, справедливо ли это в вашем случае, но будьте осторожны, чтобы измерить полную разницу во времени запуска между явной регистрацией и этой (основанной на отражении) автоматической регистрацией. Хотя накладные расходы, безусловно, существуют, они обычно меньше, чем вы думаете.

Steven 04.06.2024 15:51

«больше использования памяти». Во время запроса объектов с использованием отражения память будет временно использоваться больше, но после этапа запуска разницы в использовании памяти нет. В случае сомнений: измерьте.

Steven 04.06.2024 15:51

«Мне показалось, что статическая генерация кода во время компиляции с помощью генератора исходного кода». Генерация этого кода с помощью генератора кода, безусловно, возможна и иногда приводит к более быстрому запуску, но вы потеряете гибкость в отличие от использования этого динамического способа регистрации вещей на основе среды выполнения. Также обратите внимание, что зрелые DI-контейнеры в .NET используют этот подход на основе отражения уже почти два десятилетия, в то время как генерация кода во время компиляции для регистрации зависимостей является довольно новой.

Steven 04.06.2024 15:54

Хотя это хороший ответ, я думаю, вам, вероятно, следует упомянуть и о некоторых подводных камнях. Подобные отражения лишают вас возможности использовать AOT. Но более серьезные проблемы, подобные этой, не удастся решить, если какая-либо из служб реализует более одного интерфейса или если службы находятся в нескольких сборках.

DavidG 06.06.2024 10:54

@DavidG, кажется, ты только что упомянул AOT :-). Конечно, этот показанный пример очень ограничен. Однако то, как писать запросы автоматической регистрации, во многом зависит от соглашений, которые применяет приложение. Этот контекст полностью отсутствует в вопросе. Вопрос очень широкий, и мой ответ, следовательно, такой же. Идея состоит в том, чтобы дать ФП представление о том, как решить эту проблему и учесть потребности. Изменение этого параметра для поддержки нескольких интерфейсов и нескольких сборок не должно составить труда для опытного разработчика C#.

Steven 06.06.2024 12:51

Конечно, но вы не предоставили никакого контекста в своем ответе, поэтому люди будут слепо приходить и не иметь ни малейшего представления, почему они могут не захотеть поступать таким образом. Если бы я написал этот ответ, я, возможно, начал бы со слов: «Не делайте этого, если вы действительно не знаете, что делаете, и не имеете передовой опыт». Что касается добавления строки AOT, мы все знаем, что комментарии здесь довольно эфемерны и могут исчезнуть в любой момент, не говоря уже о том факте, что большинство людей вообще их не читают.

DavidG 06.06.2024 12:57

@DavidG, точка зрения принята. Обычно я предоставляю больше контекста в своих ответах здесь, на SO. Если вы опубликуете свой собственный ответ, я обязательно проголосую за него, как я часто делаю с вашими ответами.

Steven 06.06.2024 15:14

Другие вопросы по теме