Поделиться через


Использование внедрения зависимостей в функциях Azure .NET

Функции Azure поддерживают шаблон проектирования программного обеспечения для внедрения зависимостей (DI), который является методом для достижения инверсии элемента управления (IoC) между классами и их зависимостями.

  • Внедрение зависимостей в Функции Azure основано на функциях внедрения зависимостей .NET Core. Рекомендуется ознакомиться с внедрением зависимостей .NET Core . Существуют различия в переопределении зависимостей и в способах чтения значений конфигурации в тарифе Consumption с помощью функций Azure.

  • Поддержка внедрения зависимостей начинается с Функций Azure 2.x.

  • Шаблоны внедрения зависимостей различаются в зависимости от того, выполняются ли функции C# в процессе или вне процесса.

Это важно

Руководство в этой статье относится только к функциям библиотеки классов C#, которые выполняются в процессе с средой выполнения. Эта пользовательская модель внедрения зависимостей не применяется к изолированным функциям .NET, что позволяет запускать функции .NET вне процесса. Модель изолированного рабочего процесса .NET зависит от стандартных моделей внедрения зависимостей ASP.NET Core. Дополнительные сведения см. в руководстве по внедрению зависимостей в руководстве по изолированному рабочему процессу .NET.

Предпосылки

Прежде чем использовать внедрение зависимостей, необходимо установить следующие пакеты NuGet:

Регистрация услуг

Чтобы зарегистрировать службы, создайте метод, который настроит и добавит компоненты в экземпляр IFunctionsHostBuilder. Хост Azure Functions создает экземпляр IFunctionsHostBuilder и передает его непосредственно в ваш метод.

Предупреждение

Для приложений-функций, работающих в планах "Потребление" или "Премиум", изменения значений конфигурации, используемых в триггерах, могут привести к ошибкам масштабирования. Любые изменения этих свойств класса FunctionsStartup приводят к ошибке запуска приложения-функции.

Внедрение IConfiguration может привести к неожиданному поведению. Дополнительные сведения о добавлении источников конфигурации см. в разделе "Настройка источников конфигурации".

Чтобы зарегистрировать метод, добавьте FunctionsStartup атрибут сборки, указывающий имя типа, используемое во время запуска.

using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;

[assembly: FunctionsStartup(typeof(MyNamespace.Startup))]

namespace MyNamespace;

public class Startup : FunctionsStartup
{
    public override void Configure(IFunctionsHostBuilder builder)
    {
        builder.Services.AddHttpClient();

        builder.Services.AddSingleton<IMyService>((s) => {
            return new MyService();
        });

        builder.Services.AddSingleton<ILoggerProvider, MyLoggerProvider>();
    }
}

В этом примере используется пакет Microsoft.Extensions.Http, необходимый для регистрации компонента при запуске.

Предупреждения

Ряд шагов регистрации, выполняемых до и после выполнения, обрабатывает класс запуска. Поэтому помните о следующих элементах:

  • Класс запуска предназначен только для настройки и регистрации. Избегайте использования служб, зарегистрированных при запуске во время запуска. Например, не пытайтесь записать сообщение в средство ведения журнала, зарегистрированное во время запуска. Эта точка процесса регистрации слишком ранняя, чтобы службы были доступны для использования. Configure После запуска метода среда выполнения Функций продолжает регистрировать другие зависимости, которые могут повлиять на работу служб.

  • Контейнер внедрения зависимостей содержит только явно зарегистрированные типы. Единственными службами, доступными как внедренные типы, являются те, которые настроены в методе Configure. В результате типы, относящиеся к функциям, такие как BindingContext и ExecutionContext недоступны во время установки или в качестве внедренных типов.

  • Настройка проверки подлинности ASP.NET не поддерживается. Узел функций настраивает службы проверки подлинности ASP.NET для правильного предоставления API для основных операций жизненного цикла. Другие конфигурации в пользовательском Startup классе могут переопределить эту конфигурацию, что приводит к непредвиденным последствиям. Например, вызов builder.Services.AddAuthentication() может нарушить проверку подлинности между порталом и узлом, что ведет к сообщениям, таким как среда выполнения Функций Azure недоступна.

Использование внедренных зависимостей

Внедрение конструктора используется для того, чтобы сделать зависимости доступными в функции. Использование внедрения конструктора требует, чтобы статические классы не использовались для внедренных служб или для классов функций.

Следующий пример демонстрирует, как зависимости IMyService и HttpClient внедряются в функцию, инициируемую HTTP-запросом.

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
using System.Net.Http;
using System.Threading.Tasks;

namespace MyNamespace;

public class MyHttpTrigger
{
    private readonly HttpClient _client;
    private readonly IMyService _service;

    public MyHttpTrigger(IHttpClientFactory httpClientFactory, IMyService service)
    {
        this._client = httpClientFactory.CreateClient();
        this._service = service;
    }

    [FunctionName("MyHttpTrigger")]
    public async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
        ILogger log)
    {
        var response = await _client.GetAsync("https://microsoft.com");
        var message = _service.GetMessage();

        return new OkObjectResult("Response from function with injected dependencies.");
    }
}

В этом примере используется пакет Microsoft.Extensions.Http, необходимый для регистрации компонента при запуске.

Срок службы

Приложения Azure Functions предоставляют те же сроки жизни служб, что и внедрение зависимостей в ASP.NET. Для приложения Functions, различные временные циклы служб ведут себя следующим образом:

  • Временные: временные сервисы создаются при каждом разрешении сервиса.
  • Ограниченная область: Время существования службы с ограниченной областью соответствует времени выполнения функции. Службы с областью действия создаются один раз для каждого выполнения функции. Последующие запросы для данной службы в процессе выполнения повторно используют существующий экземпляр службы.
  • Singleton: время существования службы singleton соответствует времени существования узла и повторно используется во время выполнения функций в этом экземпляре. Службы с временем существования Singleton рекомендуются для подключений и клиентов, например, экземпляров DocumentClient или HttpClient.

Просмотрите или скачайте пример различных времен существования службы на GitHub.

Службы ведения журнала

Если вам нужен собственный поставщик ведения журнала, зарегистрируйте настраиваемый тип в качестве экземпляра ILoggerProvider, который доступен через пакет NuGet Microsoft.Extensions.Logging.Abstractions .

Application Insights автоматически добавляется функциями Azure.

Предупреждение

  • Не добавляйте AddApplicationInsightsTelemetry() в коллекцию служб, регистрирующую службы, которые конфликтуют со службами, предоставляемыми средой.
  • Не регистрируйте собственные TelemetryConfiguration или TelemetryClient если вы используете встроенные функции Application Insights. Если вам необходимо настроить собственный TelemetryClient экземпляр, создайте его с помощью внедренного TelemetryConfiguration, как показано в документе "Регистрация пользовательской телеметрии в функциях C#".

ILogger<T> и ILoggerFactory

Хост внедряет службы ILogger<T> и ILoggerFactory в конструкторы. Однако по умолчанию эти новые фильтры ведения журнала фильтруются из журналов функций. Необходимо изменить host.json файл, чтобы выбрать дополнительные фильтры и категории.

В следующем примере показано, как добавить ILogger<HttpTrigger> с журналами, которые открыты для узла.

namespace MyNamespace;

public class HttpTrigger
{
    private readonly ILogger<HttpTrigger> _log;

    public HttpTrigger(ILogger<HttpTrigger> log)
    {
        _log = log;
    }

    [FunctionName("HttpTrigger")]
    public async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req)
    {
        _log.LogInformation("C# HTTP trigger function processed a request.");

        // ...
}

В следующем примере host.json файла добавляется фильтр журнала.

{
    "version": "2.0",
    "logging": {
        "applicationInsights": {
            "samplingSettings": {
                "isEnabled": true,
                "excludedTypes": "Request"
            }
        },
        "logLevel": {
            "MyNamespace.HttpTrigger": "Information"
        }
    }
}

Дополнительные сведения об уровнях журналов см. в разделе "Настройка уровней журнала".

Сервисы приложения Function app

Хост функции регистрирует множество служб. Следующие службы безопасно использовать в качестве зависимостей в приложении:

Тип службы Продолжительность жизни Описание
Microsoft.Extensions.Configuration.IConfiguration Синглтон Конфигурация среды выполнения
Microsoft.Azure.WebJobs.Host.Executors.IHostIdProvider Синглтон Ответственность за предоставление идентификатора экземпляра узла

Если существуют другие службы, от которых требуется взять зависимость, создайте проблему и предложите их на сайте GitHub.

Переопределение служб хоста

Переопределение служб, предоставляемых узлом, в настоящее время не поддерживается. Если вы хотите переопределить службы, создайте проблему и предложите их на сайте GitHub.

Работа с параметрами и настройками

Значения, определенные в параметрах приложения , доступны в экземпляре IConfiguration , что позволяет считывать значения параметров приложения в классе запуска.

Вы можете извлечь значения из экземпляра IConfiguration в пользовательский тип. Копирование значений параметров приложения в пользовательский тип упрощает тестирование служб путем внедрения этих значений. Параметры, прочитанные в экземпляре конфигурации, должны быть простыми парами "ключ-значение". Для функций, выполняемых в плане Elastic Premium, имена параметров приложения могут содержать только буквы, цифры (), точки (0-9.), двоеточия (:) и символы подчеркивания (_). Дополнительные сведения см. в рекомендациях по настройке приложений.

Рассмотрим следующий класс, включающий свойство с именем, согласованное с параметром приложения:

public class MyOptions
{
    public string MyCustomSetting { get; set; }
}

И файл, который может структурировать настраиваемый local.settings.json параметр следующим образом:

{
  "IsEncrypted": false,
  "Values": {
    "MyOptions:MyCustomSetting": "Foobar"
  }
}

Из метода Startup.Configure можно извлечь значения из экземпляра IConfiguration в пользовательский тип с помощью следующего кода:

builder.Services.AddOptions<MyOptions>()
    .Configure<IConfiguration>((settings, configuration) =>
    {
        configuration.GetSection("MyOptions").Bind(settings);
    });

Вызов Bind копирует значения с соответствующими именами свойств из конфигурации в пользовательский экземпляр. Экземпляр параметров теперь доступен в контейнере IoC для внедрения в функцию.

Объект options внедряется в функцию в качестве экземпляра универсального IOptions интерфейса. Value Используйте свойство для доступа к значениям, найденным в конфигурации.

using System;
using Microsoft.Extensions.Options;

public class HttpTrigger
{
    private readonly MyOptions _settings;

    public HttpTrigger(IOptions<MyOptions> options)
    {
        _settings = options.Value;
    }
}

Дополнительные сведения см. в разделе "Шаблон параметров в ASP.NET Core".

Использование секретов пользователей ASP.NET Core

При локальной разработке приложения ASP.NET Core предоставляет средство диспетчера секретов , позволяющее хранить секретную информацию за пределами корневого каталога проекта. Это делает менее вероятным, что секреты случайно фиксируются в системе управления версиями. Azure Functions Core Tools (версия 3.0.3233 или более поздней версии) автоматически считывает секреты, созданные ASP.NET Core Secret Manager.

Чтобы настроить проект Функций Azure .NET для использования секретов пользователей, выполните следующую команду в корневом каталоге проекта.

dotnet user-secrets init

Затем используйте dotnet user-secrets set команду для создания или обновления секретов.

dotnet user-secrets set MySecret "my secret value"

Чтобы получить доступ к значениям секретов пользователей в коде приложения-функции, используйте IConfiguration или IOptions.

Настройка источников конфигурации

Чтобы указать другие источники конфигурации, необходимо переопределить метод ConfigureAppConfiguration в классе вашего приложения с функцией StartUp.

Следующий пример добавляет значения конфигурации как из базовых, так и необязательных файлов параметров приложения для конкретной среды.

using System.IO;
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

[assembly: FunctionsStartup(typeof(MyNamespace.Startup))]

namespace MyNamespace;

public class Startup : FunctionsStartup
{
    public override void ConfigureAppConfiguration(IFunctionsConfigurationBuilder builder)
    {
        FunctionsHostBuilderContext context = builder.GetContext();

        builder.ConfigurationBuilder
            .AddJsonFile(Path.Combine(context.ApplicationRootPath, "appsettings.json"), optional: true, reloadOnChange: false)
            .AddJsonFile(Path.Combine(context.ApplicationRootPath, $"appsettings.{context.EnvironmentName}.json"), optional: true, reloadOnChange: false)
            .AddEnvironmentVariables();
    }
    
    public override void Configure(IFunctionsHostBuilder builder)
    {
    }
}

Добавьте поставщиков конфигурации в ConfigurationBuilder свойство IFunctionsConfigurationBuilder. Дополнительные сведения об использовании поставщиков конфигураций см. в разделе "Конфигурация" в ASP.NET Core.

A FunctionsHostBuilderContext получается из IFunctionsConfigurationBuilder.GetContext(). Используйте этот контекст для получения текущего имени среды и разрешения расположения файлов конфигурации в папке приложения-функции.

По умолчанию файлы конфигурации, такие как appsettings.json не копируются автоматически в выходную папку приложения-функции. Обновите .csproj файл, чтобы он соответствовал следующему образцу, чтобы убедиться, что файлы копируются.

<None Update="appsettings.json">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>      
</None>
<None Update="appsettings.Development.json">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    <CopyToPublishDirectory>Never</CopyToPublishDirectory>
</None>

Дальнейшие шаги

Дополнительные сведения см. в следующих ресурсах: