Содержание
Как мы уже знаем, методы регистрации зависимостей имеют название, соответствующее шаблону 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 (временный). Аналогичные методы используются и для сервисов с другим жизненным циклом. Выбор того или иного метода регистрации зависит от конкретной ситуации — имеет ли сервис множество реализаций или только одну, требуется ли сложна логика создания реализации сервиса или нет и так далее.