Инверсия зависимостей (Dependency injection) - очень мощный инструмент управления приложением. Позволяет управлять логикой создания реализаций в приложении. Для этого в приложение создают контейнер с зависимостями в котором регистрируют все связки интерфейс-реализация, после из этого контейнера можно получить зависимость по интерфейсу, если для построения требуемой зависимости необходимы другие интерфейсы, то они инициализируются в соответствии с прочими зарегистрированными связками. Это позволяет отвязаться от конкретных реализаций в зависимостях и конфигурировать их заранее
<aside> 🐺 Подробней про это можно почитать тут https://learn.microsoft.com/ru-ru/dotnet/architecture/modern-web-apps-azure/architectural-principles#dependency-inversion.
</aside>
Давайте попробуем:
Давайте попробуем воспользоваться им:
dotnet new console -o lesson10
Заменим код Program.cs на:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using var host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddOptions<AppSettings>().BindConfiguration(nameof(AppSettings));
})
.Build();
var options = host.Services.GetRequiredService<IOptions<AppSettings>>();
Console.WriteLine($"{options.Value.FirstWord} {options.Value.SecondWord} {options.Value.Versions[0].Number}");
Добавим файл AppSettings.cs:
public class AppSettings
{
public string? FirstWord { get; set; }
public string? SecondWord { get; set; }
public class Version
{
public int Number { get; set; }
}
public List<Version> Versions { get; set; } = new();
}
Создайте новый файл appsettings.json в том же каталоге, что и ваш файл Program.cs.
{
"AppSettings": {
"FirstWord": "Hello",
"SecondWord": "dotnet",
"Versions": [
{
"Number": 7
}
]
}
}
Создайте новый файл appsettings.Development.json в том же каталоге, что и ваш файл Program.cs.
{
"AppSettings": {
"Versions": [
{
"Number": 8
}
]
}
}
В консоле перейдите в папку с проектом.
Установим зависимость через dotnet cli:
dotnet add package Microsoft.Extensions.Hosting --version 7.0.1
Добавление пакетов отразится в файле lesson10.csproj
Вместо имени файла укажите шаблон appsettings*.json в csproj, все файлы подходящие под него будут копироваться в директорию при сборке проекта. Давайте добавим нужную настройку в lesson10.csproj.
<ItemGroup>
<Content Include="appsettings*.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
Должно получиться следующее:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
</ItemGroup>
<ItemGroup>
<Content Include="appsettings*.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>
В этом уроке мы подключаем DI и добавить в него конфигурацию. На что тут стоит обратить внимание:
Импортировали зависимость Microsoft.Extensions.DependencyInjection - нужна для использования методов AddOptions и GetRequiredService. Метод AddOptions позволяет добавить в DI конфигурацию. Метод GetRequiredService позволяет получить из DI любую зависимость, в случае если зависимости нет будет выброшено исключение.
<aside>
🐺 Подробней про AddOptions можно почитать тут https://learn.microsoft.com/ru-ru/aspnet/core/fundamentals/configuration/options?view=aspnetcore-7.0#optionsbuilder-api.
</aside>
<aside>
🐺 Подробней про GetRequiredService можно почитать тут https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.serviceproviderserviceextensions.getrequiredservice?view=dotnet-plat-ext-7.0.
</aside>
Импортировали зависимость Microsoft.Extensions.Options - нужна для использования класса IOptions<T>.
<aside>
🐺 Подробней про IOptions<T> и другие его разновидности можно почитать тут https://learn.microsoft.com/ru-ru/aspnet/core/fundamentals/configuration/options?view=aspnetcore-7.0#options-interfaces.
</aside>
Метод ConfigureServices зависимости Microsoft.Extensions.Hosting позволяет настроить DI путём добавления в services новых зависимостей.
Метод BindConfiguration - позволяет настроить маппинг напрямую по названию секции в конфигурации.
Запустите приложение с полным набором параметров:
DOTNET_ENVIRONMENT=Development \
AppSettings__Versions__0__Number=9 \
dotnet run AppSettings:Versions:0:Number=10
Вы получите вывод:
Hello dotnet 10
Можете поэкспериментировать и удостовериться что всё работает так же как в уроке 7.
<aside> 🐺 В этом уроке мы научились добавлять настройки приложения в DI. Это позволи нам получать доступ к настройкам в любой зависимости сервиса. Подробней про это можно почитать тут https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-7.0.
</aside>
<aside> 💡 Решение доступно тут https://github.com/vahpetr/lessions/tree/main/lesson10
</aside>