#c# #.net-core #azure-functions
#c# #.net-ядро #azure-функции
Вопрос:
У меня возникла проблема с регистрацией синглтона с помощью Microsoft.Extensions.DependencyInjection
. Я создал Startup
класс (который определенно работает) и создал ITestService
с реализацией.
Синглтон вводится в конструктор функции. Изначально у меня не было проблем с этой реализацией, однако через пару дней функция завершается сбоем, потому что она не может решить ITestService
. Я понятия не имею, почему.
вот Startup
класс
using Microsoft.Azure.WebJobs.Hosting;
[assembly: WebJobsStartup(typeof(Startup))]
namespace Test.Functions
{
using System;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
public class Startup : IWebJobsStartup
{
public void Configure(IWebJobsBuilder builder)
{
var configuration = new ConfigurationBuilder()
.SetBasePath(Environment.CurrentDirectory)
.AddJsonFile("local.settings.json", true, true)
.AddEnvironmentVariables()
.Build();
builder.Services.AddSingleton<ITestService>(new TestService("test string"));
}
}
}
И вот функция
public class TestFunction
{
private readonly ITestService testService
public TestFunction(ITestService testService)
{
this.testService = testService ?? throw new ArgumentNullException(nameof(testService));
}
[FunctionName(nameof(TestFunction))]
public void Run([ServiceBusTrigger("test", Connection = "ServiceBusConnection")]Message message, ILogger log)
{
////use test service here
}
}
Когда я отлаживаю запуск и смотрю на Services
, я вижу, что тип реализации — null
for ITestService
, который, как я предполагаю, является причиной того, что он не будет разрешен. Как я уже упоминал, это полностью работало в течение пары дней. Версия функций и т.д. Не изменилась. Будем признательны за любые идеи, как заставить это снова работать.
Обновить
Я попытался упростить это еще больше и создал другой фиктивный интерфейс с реализацией, которая имеет конструктор без параметров. Я добавил его с помощью: builder.AddSingleton<ITestService2, TestService2>()
Очевидно, что тип был присвоен типу реализации, но когда пришло время внедрить его в конструктор, произошел сбой с тем же исключением «не удается активировать».
Комментарии:
1. Вы пробовали это с сервисами. BuildServiceProvider();
2. @Azzy Я попробовал, но это не решило проблему.
Ответ №1:
В последней версии узла функций произошел регресс, из-за которого внедрение зависимостей не удалось.
Чтобы обойти это в среде Azure, вы можете заблокировать конкретную версию узла функций, установив для FUNCTIONS_EXTENSION_VERSION
параметра приложения значение 2.0.12342.0
.
Если вы запускаете функцию host локально, используя azure-functions-core-tools
пакет NPM, обязательно используйте 2.4.419
, поскольку последняя версия (2.4.498) приводит к той же проблеме. Вы можете установить это явно с помощью следующего:
npm i -g azure-functions-core-tools@2.4.419
Смотрите эту проблему на GitHub для получения дополнительной информации.
Ответ №2:
Попробуйте это в своем коде:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ITestService, TestService>();
}
Комментарии:
1. О даунвотере. Предложение правильное. Проверьте документацию: learn.microsoft.com/en-us/dotnet/api /… . Хорошей практикой должно быть объяснение причины снижения.
2. @AzzyElvul Похоже, что вызов
builder.Services.AddSingleton<ITestService>(new TestService("test string"));
также правильный, и предложение может просто не отвечать на первоначальный вопрос…3. Я не голосовал против, но если вы заметили, что TestService принимает строку в качестве параметра, поэтому ваше решение для этого не будет работать
4. К сожалению, это не сработает, поскольку при запуске зависимости
TestService
требуется строковое значение для удовлетворения конструктора.
Ответ №3:
Попробуйте это
builder.Services.AddSingleton<ITestService>(s => new TestService("test string"));
При этом используется IServiceProvider
для того, чтобы предоставить string
параметр конструктору.
Редактировать :
Попробуйте изменить свой код на приведенный ниже и установить Willezone.Azure.Веб-задания.Расширения.DependencyInjection
Это добавляет метод расширения AddDependencyInjection
и позволяет выполнять традиционный ConfigureServices
вызов метода при запуске приложения net core.
using Microsoft.Azure.WebJobs.Hosting;
[assembly: WebJobsStartup(typeof(Startup))]
namespace Test.Functions
{
using System;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
public class Startup : IWebJobsStartup
{
public void Configure(IWebJobsBuilder builder)
{
var configuration = new ConfigurationBuilder()
.SetBasePath(Environment.CurrentDirectory)
.AddJsonFile("local.settings.json", true, true)
.AddEnvironmentVariables()
.AddDependencyInjection(ConfigureServices)
.Build();
}
private void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ITestService>(s => new TestService("test string"));
}
}
}
Комментарии:
1. Я пробовал это, но результат все тот же. На самом деле это имело большой смысл, потому что это то, что я делаю, когда использую Autofac.
2. @AnotherDev очень странно. Мы используем этот подход повсеместно, и он отлично работает.
3. Этот метод расширения фактически зависает от объекта builder so builder. Добавление зависимостей (ConfigureService). Я пробовал это и все еще без кубиков