Содержание
Как мы уже знаем, методы регистрации зависимостей имеют название, соответствующее шаблону Add[Lifecycle]()
или AddKeyed[Lifecycle]()
. При этом, каждый из методов имеет ряд переопределенных версий. В этой части мы рассмотрим различные методы регистрации сервисов и их применение в приложениях .NET MAUI.
Методы регистрации сервисов
Стоит отметить, что методы расширения для регистрации сервисов, вне зависимости от жизненного цикла сервиса, имеют схожие параметры. Поэтому нет смысла дублировать информацию о том или ином методе регистрации несколько раз только исходя из того, что меняется жизненный цикл сервиса. Ниже мы рассмотрим все методы только для transient-сервисов. Методы расширения IServiceCollection
для регистрации transient-сервисов в .NET 9 выглядят следующим образом:
Метод | Параметры метода | |
1 |
public static IServiceCollection AddTransient(this IServiceCollection services, Type serviceType); |
|
2 |
public static IServiceCollection AddTransient<TService>(this IServiceCollection services) where TService : class; |
Универсальная версия предыдущего метода.
|
3 |
public static IServiceCollection AddTransient(this IServiceCollection services, Type serviceType, Func<IServiceProvider,object> implementationFactory); |
|
4 |
public static IServiceCollection AddTransient<TService>(this IServiceCollection services, Func<IServiceProvider,TService> implementationFactory) where TService : class; |
Универсальная версия предыдущего метода:
|
5 |
public static IServiceCollection AddTransient(this IServiceCollection services, Type serviceType, Type implementationType); |
|
6 |
public static IServiceCollection AddTransient<TService,TImplementation>(this IServiceCollection services) where TService : class where TImplementation : class, TService; |
Универсальная версия предыдущего метода
|
7 |
public static IServiceCollection AddTransient<TService,TImplementation>(this IServiceCollection services, Func<IServiceProvider,TImplementation> implementationFactory) where TService : class where TImplementation : class, TService; |
|
Также можно использовать семь версий методов вида AddKeyedTransient()
. Отличие этих методов от представленных выше заключается только в наличие ещё одного параметра — serviceKey
типа object
— ключа сервиса. Сервисы с ключами и их применение мы рассмотрим чуть позже, а пока остановимся на обычных сервисах. Каждый из этих методов может оказаться удобным в определенных случаях.
Первые две версии метода:
public static IServiceCollection AddTransient(this IServiceCollection services, Type serviceType); public static IServiceCollection AddTransient<TService>(this IServiceCollection services) where TService : class;
удобно использовать в том случае, когда сервис имеет всего одну реализацию. Например, сейчас наш сервис ILogger
имеет всего одну реализацию — класс FileLogger
. И, если не предполагается, что у сервиса могут появиться когда-либо другие реализации, то, в этом случае, нет никакой необходимости создавать отдельный сервис и, затем, реализовывать его в классе. Можно просто зарегистрировать в качестве сервиса конкретный класс:
builder.Services.AddTransient(typeof(FileLogger)); //первый вариант builder.Services.AddTransient<FileLogger>();//второй вариант
Версии метода с использованием фабрики:
public static IServiceCollection AddTransient(this IServiceCollection services, Type serviceType, Func<IServiceProvider,object> implementationFactory); public static IServiceCollection AddTransient<TService>(this IServiceCollection services, Func<IServiceProvider,TService> implementationFactory) where TService : class;
Использование фабрики при регистрации сервиса может оказаться удобной в случае, если вам требуется более сложная логика создания объекта сервиса, чем обычный вызов конструктора класса. Например, мы захотим передать в сервис дополнительную информацию, через его свойство:
public class FileLogger: ILogger { const string FILE_NAME = "Log.txt"; private readonly DateTime _currentTime; private string fileName; public string FileName { get { return fileName; } set { fileName = value; } } private readonly string _newLine = Environment.NewLine; public FileLogger() { _currentTime = DateTime.Now; fileName = FILE_NAME; } public void WriteLine(string message) { File.AppendAllText(fileName, $"[{_currentTime}] - {message}{_newLine}"); } }
Один из вариантов это сделать — воспользоваться методом с фабрикой:
builder.Services.AddTransient(typeof(ILogger), (provider) => { return new FileLogger() { FileName = "Log.txt" }; }); //ИЛИ ТАК builder.Services.AddTransient<FileLogger>((provider) => { return new FileLogger() { FileName = "Log.txt" }; });
Следующие две версии метода применяются в том случае, если наш сервис предполагает множество реализаций. В этом случае мы указываем в параметрах тип сервиса (интерфейс) и его конкретную реализацию, которая будет использоваться в приложении:
builder.Services.AddTransient(typeof(ILogger), typeof(FileLogger)); //ИЛИ builder.Services.AddTransient<ILogger, FileLogger>();
И, наконец, последняя версия метода
public static IServiceCollection AddTransient<TService,TImplementation>(this IServiceCollection services, Func<IServiceProvider,TImplementation> implementationFactory) where TService : class where TImplementation : class, TService;
совмещает в себе все преимущества — здесь мы можем не только использовать сервис и его реализацию, но и применить фабрику при создании объекта сервиса:
builder.Services.AddTransient<ILogger, FileLogger>((provider) => { return new FileLogger() { FileName = "Log.txt" }; });
Итого
Выше мы рассмотрели методы регистрации сервисов с жизненным циклом transient (временный). Аналогичные методы используются и для сервисов с другим жизненным циклом. Выбор того или иного метода регистрации зависит от конкретной ситуации — имеет ли сервис множество реализаций или только одну, требуется ли сложна логика создания реализации сервиса или нет и так далее.