Как WebApplication.CreateBuilder().Services.AddTransient() работает в ASP.NET Core MVC? ⇐ C#
-
Гость
Как WebApplication.CreateBuilder().Services.AddTransient() работает в ASP.NET Core MVC?
Я использую веб-приложение ASP.NET Core MVC. У меня есть модель под названием Район:
публичный класс DistrictModel { общественный ИНТ District_id {получить; набор; } общественная строка имя_района {получить; набор; } } У меня есть два источника данных для округов: один — тестовые данные в файле JSON, а другой — производственные данные в базе данных SQL Server.
Чтобы упростить переключение между источниками данных (полагаю, это называется инверсией зависимостей?) я создал интерфейс для определения функций получения данных:
публичный интерфейс IDistrictServices { List GetAllDistricts(); DistrictModel GetDistrictByID (int District_id); List SearchDistricts (строка search_term); } И я использовал интерфейс обоих классов для получения JSON и SQL.
Класс JSON:
публичный класс DistrictJSON: IDistrictServices { общедоступный список GetAllDistricts() { строка District_file_location = @"wwwroot/data/districts.json"; //переносим это в конфигурацию строка jsonString = File.ReadAllText(district_file_location); List Found_districts = JsonSerializer.Deserialize(jsonString); вернуть найденные_районы; } } Класс SQL Server:
публичный класс DistrictSQL: IDistrictServices { //переносим строку подключения в конфиг string Connection_string = @"Источник данных=SWSQLDEV001;Идентификатор пользователя=thannah;Пароль=*****;Время ожидания соединения=30;Шифрование=False;База данных=CapV3;"; общедоступный список GetAllDistricts() { List Found_districts = новый List(); строка sql_statement = @" ВЫБЕРИТЕ дд.id, дд.полное имя ОТ районадим дд Версии INNER JOIN v ON v.districtid = dd.id WHERE v.version = 'Текущий прогноз' "; используя (соединение SqlConnection = новый SqlConnection(connection_string)) { Команда SqlCommand = новая SqlCommand (sql_statement, соединение); пытаться { соединение.Открыть (); Читатель SqlDataReader = команда.ExecuteReader(); пока (читатель.Читать()) { Found_districts.Add(new DistrictModel { District_id = (int) Reader [0], District_name = (string) Reader [1] }); } } поймать (Исключение ex) { Console.WriteLine(ex.Message); } } вернуть найденные_районы; } } Мой контроллер получает все районы и отправляет их для просмотра:
публичный класс DistrictController: Контроллер { общественный список округов IDistrictServices {get; набор; } общедоступный DistrictController (служба данных IDistrictServices) { список округов = служба данных; } публичный индекс IActionResult() { return View(districtlist.GetAllDistricts()) ; } } Program.cs определяет, какой сервис используется: JSON или SQL Server:
с использованием OperationalForecast.Services; вар строитель = WebApplication.CreateBuilder(args); // Добавляем сервисы в контейнер. builder.Services.AddTransient(); //builder.Services.AddTransient(); builder.Services.AddControllersWithViews(); вар приложение = builder.Build(); // Настраиваем конвейер HTTP-запросов. если (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Home/Error"); // Значение HSTS по умолчанию — 30 дней. Возможно, вы захотите изменить это для рабочих сценариев, см. https://aka.ms/aspnetcore-hsts. приложение.UseHsts(); } app.UseHttpsRedirection(); приложение.UseStaticFiles(); приложение.UseRouting(); приложение.UseAuthorization(); приложение.MapControllerRoute( имя: «по умолчанию», шаблон: "{controller=Home}/{action=Index}/{id?}"); приложение.Выполнить(); Я добавил две строки кода:
builder.Services.AddTransient(); //builder.Services.AddTransient(); Какую бы строку я не оставил без комментариев, это и есть используемый класс. Если я оставлю обе строки без комментариев, будет использована вторая строка.
У меня вопрос: как это на самом деле работает? В какой-то момент вызывается конструктор DistrictController (я полагаю, каждый раз, когда используется URL-адрес /District? Или только один раз за сеанс?). Как этот код может узнать, что я намереваюсь использовать указанный класс для контроллера District, а не для какого-либо другого контроллера? Что делать, если у меня несколько интерфейсов и мне нужно передать несколько интерфейсов контроллеру?
Эта часть похожа на PFM, и я боюсь, что если я не пойму, как она работает, я не смогу завершить свое заявление.
Я использую веб-приложение ASP.NET Core MVC. У меня есть модель под названием Район:
публичный класс DistrictModel { общественный ИНТ District_id {получить; набор; } общественная строка имя_района {получить; набор; } } У меня есть два источника данных для округов: один — тестовые данные в файле JSON, а другой — производственные данные в базе данных SQL Server.
Чтобы упростить переключение между источниками данных (полагаю, это называется инверсией зависимостей?) я создал интерфейс для определения функций получения данных:
публичный интерфейс IDistrictServices { List GetAllDistricts(); DistrictModel GetDistrictByID (int District_id); List SearchDistricts (строка search_term); } И я использовал интерфейс обоих классов для получения JSON и SQL.
Класс JSON:
публичный класс DistrictJSON: IDistrictServices { общедоступный список GetAllDistricts() { строка District_file_location = @"wwwroot/data/districts.json"; //переносим это в конфигурацию строка jsonString = File.ReadAllText(district_file_location); List Found_districts = JsonSerializer.Deserialize(jsonString); вернуть найденные_районы; } } Класс SQL Server:
публичный класс DistrictSQL: IDistrictServices { //переносим строку подключения в конфиг string Connection_string = @"Источник данных=SWSQLDEV001;Идентификатор пользователя=thannah;Пароль=*****;Время ожидания соединения=30;Шифрование=False;База данных=CapV3;"; общедоступный список GetAllDistricts() { List Found_districts = новый List(); строка sql_statement = @" ВЫБЕРИТЕ дд.id, дд.полное имя ОТ районадим дд Версии INNER JOIN v ON v.districtid = dd.id WHERE v.version = 'Текущий прогноз' "; используя (соединение SqlConnection = новый SqlConnection(connection_string)) { Команда SqlCommand = новая SqlCommand (sql_statement, соединение); пытаться { соединение.Открыть (); Читатель SqlDataReader = команда.ExecuteReader(); пока (читатель.Читать()) { Found_districts.Add(new DistrictModel { District_id = (int) Reader [0], District_name = (string) Reader [1] }); } } поймать (Исключение ex) { Console.WriteLine(ex.Message); } } вернуть найденные_районы; } } Мой контроллер получает все районы и отправляет их для просмотра:
публичный класс DistrictController: Контроллер { общественный список округов IDistrictServices {get; набор; } общедоступный DistrictController (служба данных IDistrictServices) { список округов = служба данных; } публичный индекс IActionResult() { return View(districtlist.GetAllDistricts()) ; } } Program.cs определяет, какой сервис используется: JSON или SQL Server:
с использованием OperationalForecast.Services; вар строитель = WebApplication.CreateBuilder(args); // Добавляем сервисы в контейнер. builder.Services.AddTransient(); //builder.Services.AddTransient(); builder.Services.AddControllersWithViews(); вар приложение = builder.Build(); // Настраиваем конвейер HTTP-запросов. если (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Home/Error"); // Значение HSTS по умолчанию — 30 дней. Возможно, вы захотите изменить это для рабочих сценариев, см. https://aka.ms/aspnetcore-hsts. приложение.UseHsts(); } app.UseHttpsRedirection(); приложение.UseStaticFiles(); приложение.UseRouting(); приложение.UseAuthorization(); приложение.MapControllerRoute( имя: «по умолчанию», шаблон: "{controller=Home}/{action=Index}/{id?}"); приложение.Выполнить(); Я добавил две строки кода:
builder.Services.AddTransient(); //builder.Services.AddTransient(); Какую бы строку я не оставил без комментариев, это и есть используемый класс. Если я оставлю обе строки без комментариев, будет использована вторая строка.
У меня вопрос: как это на самом деле работает? В какой-то момент вызывается конструктор DistrictController (я полагаю, каждый раз, когда используется URL-адрес /District? Или только один раз за сеанс?). Как этот код может узнать, что я намереваюсь использовать указанный класс для контроллера District, а не для какого-либо другого контроллера? Что делать, если у меня несколько интерфейсов и мне нужно передать несколько интерфейсов контроллеру?
Эта часть похожа на PFM, и я боюсь, что если я не пойму, как она работает, я не смогу завершить свое заявление.
Мобильная версия