paint-brush
3 простых совета по внедрению зависимостей с помощью Scrutor в C#к@devleader
430 чтения
430 чтения

3 простых совета по внедрению зависимостей с помощью Scrutor в C#

к Dev Leader7m2024/03/04
Read on Terminal Reader

Слишком долго; Читать

Изучите передовые методы внедрения зависимостей с помощью Scrutor на C#. Узнайте, как оптимизировать регистрацию и разрешение, реализовать ведение журнала с помощью шаблона декоратора и использовать переключатели функций для реализации динамических сервисов. Улучшите свои приложения ASP.NET Core с помощью экспертных стратегий для эффективной организации кода и управления им!
featured image - 3 простых совета по внедрению зависимостей с помощью Scrutor в C#
Dev Leader HackerNoon profile picture
0-item

Внедрение зависимостей в C# — это спасение при организации зависимостей, особенно в более сложных приложениях ASP.NET Core. А если вы уже знакомы с IServiceCollection или просто хотите максимально приблизиться к уже предоставленным предложениям DI, Scrutor на C# станет отличным усовершенствованием.


В этой статье я предоставлю вам общий обзор внедрения зависимостей и Scrutor в C#. Но далее мы сразу перейдем к трем советам, которые вы можете использовать со Scrutor и которые могут оказаться очень полезными в вашем приложении!


Что такое Scrutor в C#?

Scrutor — это мощный пакет NuGet на C#, который расширяет возможности внедрения зависимостей. Он упрощает регистрацию и разрешение зависимостей, упрощая управление и организацию кода.


Внедрение зависимостей — популярный подход к настройке приложений, который способствует слабой связи и улучшает тестируемость и удобство обслуживания. Он предполагает внедрение зависимостей в класс, а не непосредственное их создание внутри класса. Это означает, что ответственность за создание зависимости лежит не на классе, которому она требуется, а на ком-то из верхнего стека вызовов. В конечном итоге это приводит к тому, что почти все создание зависимостей приходится на точку входа приложения, что делает его громоздким. Однако фреймворки внедрения зависимостей помогают очистить и упорядочить всю эту логику .


Scrutor развивает эту концепцию на шаг дальше, предоставляя простой и интуитивно понятный способ регистрации и разрешения зависимостей. Благодаря Scrutor вам больше не нужно вручную регистрировать каждую зависимость одну за другой. Вместо этого вы можете использовать соглашения и атрибуты для автоматизации процесса.

1 – Использование Scrutor для регистрации и разрешения

Чтобы проиллюстрировать, как использовать Scrutor на C# для регистрации и разрешения, давайте рассмотрим простой сценарий. Представьте, что у нас есть приложение, которое требует использования разных репозиториев данных, таких как UserRepository и ProductRepostiory.


Сначала нам нужно установить пакет Scrutor NuGet в наш проект. Откройте консоль диспетчера пакетов и выполните следующую команду:

 Install-Package Scrutor


Далее нам нужно определить наши репозитории и соответствующие им интерфейсы. Этот пример по сути пустой, но мы вернемся к ним через мгновение:

 public interface IUserRepository { // Interface methods } public class UserRepository : IUserRepository { // Implementation } public interface IProductRepository { // Interface methods } public class ProductRepository : IProductRepository { // Implementation }


Теперь давайте подключим наши зависимости с помощью Scrutor. В код запуска (например, в методе ConfigurationServices в ASP.NET Core) добавьте следующий код:

 services.Scan(scan => scan .FromAssemblyOf<Startup>() .AddClasses(classes => classes.AssignableToAny( typeof(IUserRepository), typeof(IProductRepository))) .AsImplementedInterfaces() .WithScopedLifetime());


Этот код использует метод Scan из Scrutor для сканирования сборки, содержащей класс Startup. Затем он отфильтровывает классы, которые можно назначить интерфейсам IUserRepository или IProductRepository. Наконец, он отображает реализации этих интерфейсов и регистрирует их в соответствующих интерфейсах.


Теперь мы можем внедрить эти зависимости в наши классы. Например, предположим, что у нас есть класс UserService, которому требуется IUserRepository:

 public class UserService { private readonly IUserRepository _userRepository; public UserService(IUserRepository userRepository) { _userRepository = userRepository; } // Rest of the class implementation }


Объявив IUserRepository как зависимость в конструкторе, Scrutor вместе с IServiceCollection автоматически разрешит и внедрит для нас экземпляр UserRepository.


2. Шаблон «Декоратор» — пример ведения журнала для сервисов.

Представьте, что у вас есть сервисный интерфейс IService и реализация MyService . Вы хотите регистрировать вход и выход каждого вызова метода в MyService , не загрязняя его бизнес-логику проблемами ведения журнала.


Сначала определите интерфейс IService и его реализацию:

 public interface IService { void DoWork(); } public class MyService : IService { public void DoWork() { // Business logic here } }


Затем создайте класс декоратора LoggingDecorator , реализующий IService . Этот класс обернет реальную службу и добавит ведение журнала вокруг вызовов делегированных методов:

 public class LoggingDecorator : IService { private readonly IService _decorated; private readonly ILogger<LoggingDecorator> _logger; public LoggingDecorator(IService decorated, ILogger<LoggingDecorator> logger) { _decorated = decorated; _logger = logger; } public void DoWork() { _logger.LogInformation("Starting work."); _decorated.DoWork(); _logger.LogInformation("Finished work."); } }


Теперь используйте Scrutor, чтобы зарегистрировать свой сервис и его декоратор в Startup.cs или там, где вы настраиваете свои сервисы:

 public void ConfigureServices(IServiceCollection services) { // Register the base service services.AddScoped<IService, MyService>(); // Use Scrutor to apply the decorator services.Decorate<IService, LoggingDecorator>(); // Make sure to register the ILogger or ILogger<T> dependencies if not already done }


В этой настройке Scrutor используется для обертывания регистрации IService с помощью LoggingDecorator . При разрешении IService контейнер DI предоставит экземпляр LoggingDecorator , который, в свою очередь, является оболочкой экземпляра MyService . Этот подход обеспечивает разделение задач, сохраняя логику журналирования вне вашей бизнес-логики.


3 – Переключение функций для реализации сервисов

Когда мы создаем сложные системы, часто бывают случаи, когда нам нужно ввести что-то вроде флагов функций. Это позволяет нам использовать разные пути кода в зависимости от конфигурации и не перекомпилировать и развертывать все приложение. В некоторых ситуациях речь идет не просто о выборе другого пути кода, а о замене всей реализации чего-либо!

Давайте попробуем пример вместе! Предположим, у вас есть интерфейс IFeatureService с несколькими реализациями: NewFeatureService (новая экспериментальная функция) и StandardFeatureService (текущая стабильная функция). Вы хотите переключаться между этими реализациями во время выполнения на основе флага конфигурации.


Сначала определите интерфейс IFeatureService и его реализации:

 public interface IFeatureService { void ExecuteFeature(); } public class NewFeatureService : IFeatureService { public void ExecuteFeature() { // New feature logic } } public class StandardFeatureService : IFeatureService { public void ExecuteFeature() { // Standard feature logic } }


Далее вам нужен способ определить, какую реализацию использовать на основе настройки переключения функций. Это может быть значение в appsettings.json , параметр базы данных или любой другой источник конфигурации.


Теперь используйте Scrutor для динамической регистрации соответствующей реализации сервиса на основе переключения функции:

 public void ConfigureServices(IServiceCollection services) { // Assume GetFeatureToggleValue() retrieves the current feature toggle setting var useNewFeature = GetFeatureToggleValue("UseNewFeature"); // Dynamically register the appropriate implementation based on the feature toggle if (useNewFeature) { services.AddScoped<IFeatureService, NewFeatureService>(); } else { services.AddScoped<IFeatureService, StandardFeatureService>(); } // Optional: You could combine this with the previous example // to use the decorator pattern too! // services.Decorate<IFeatureService, FeatureServiceProxy>(); } private bool GetFeatureToggleValue(string featureName) { // This method would typically check your // configuration source to determine if the feature is enabled // For simplicity, this is just a placeholder return false; // or true based on actual configuration }


Такой подход может помочь нам:

  • Гибкость : позволяет приложению переключаться между реализациями функций без необходимости повторного развертывания. Вы можете включить или отключить функции, просто изменив конфигурацию.
  • Тестирование в рабочей среде . Вы можете протестировать новые функции в производственной среде с ограниченным набором пользователей, включив эту функцию для этих пользователей.
  • Постепенное развертывание : помогает постепенно развертывать функции, чтобы отслеживать влияние и обеспечивать стабильность перед более широким выпуском.
  • Снижение рисков : быстро вернитесь к старой реализации, если возникнут проблемы с новой функцией, что сводит к минимуму время простоя и влияние на пользователей.

Завершение Scrutor на C#

В этой статье я предоставил вам 3 простых совета по внедрению зависимостей с помощью Scrutor в C#. После краткого обзора того, что такое внедрение зависимостей и как Scrutor в него вписывается, мы сразу перешли к нашим примерам. Мы увидели сканирование сборок, как декорировать зависимости и даже как помечать функции целыми реализациями!


Внедрение зависимостей — это то, что может значительно упростить ваши приложения по мере их усложнения, и Scrutor может оказаться огромным подспорьем, если вы хотите придерживаться встроенного предложения IServiceCollection от Microsoft . Если вы нашли это полезным и ищете дополнительные возможности для обучения, рассмотрите возможность подписки на мой бесплатный еженедельный информационный бюллетень по разработке программного обеспечения и посмотрите мои бесплатные видеоролики на YouTube ! Присоединяйтесь ко мне и другим участникам сообщества в Discord !


Также опубликовано здесь.