Внедрение зависимостей .NET Core 2.2 Azure Function v2

#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). Я пробовал это и все еще без кубиков