استخدام إدراج التبعية في Azure Functions على .NET

يدعم Azure Functions نمط تصميم برامج إدراج التبعية (DI)، وهو أسلوب لتحقيق عكس التحكم (IoC) بين الفئات وتبعياتها.

  • تم إنشاء إدراج التبعية في Azure Functions على ميزات إدراج التبعية في .NET Core. ويوصى بالإلمام بـ إدراج التبعية في .NET Core. هناك اختلافات في كيفية منع التبعيات وكيفية قراءة قيم التكوين مع Azure Functions في خطة الاستهلاك.

  • يبدأ دعم إدراج التبعية مع Azure Functions 2.x.

  • تختلف أنماط إدراج التبعية اعتمادًا على ما إذا كانت وظائف C# تعمل أثناء العملية أو خارج العملية.

هام

تنطبق الإرشادات في هذه المقالة فقط على وظائف مكتبة فئة C#‎، والتي تعمل أثناء التشغيل مع وقت التشغيل. لا ينطبق نموذج إدخال التبعية المخصص هذا على وظائف .NET المعزولة، مما يتيح لك تشغيل وظائف .NET خارج العملية. يعتمد نموذج عملية العامل المعزول .NET على أنماط حقن التبعية الأساسية ASP.NET الأساسية. لمعرفة المزيد، راجع إدخال التبعية في دليل عملية العامل المعزول .NET.

المتطلبات الأساسية

قبل أن تتمكن من استخدام إدراج التبعية، يجب تثبيت حزم NuGet التالية:

تسجيل الخدمات

لتسجيل الخدمات، قم بإنشاء أسلوب لتكوين المكونات وإضافتها إلى مثيل IFunctionsHostBuilder. يقوم مضيف Azure Functions بإنشاء مثيل IFunctionsHostBuilder ويمرره مباشرة إلى أسلوبك.

تحذير

بالنسبة لتطبيقات الدالات التي تعمل في خطط Consumption أو Premium، يمكن أن تؤدي التعديلات في قيم التكوين المستخدمة في المشغلات إلى حدوث أخطاء في التحجيم. أي تغييرات في هذه الخصائص من قبل فئة 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 المطلوبة لتسجيل HttpClient عند بدء التشغيل.

تحذيرات

يتم تشغيل سلسلة من خطوات التسجيل قبل وبعد عمليات وقت التشغيل لفئة بدء التشغيل. لذلك، ضع في الاعتبار العناصر التالية:

  • فئة بدء التشغيل مخصصة فقط للإعداد والتسجيل. تجنب استخدام الخدمات المسجلة عند بدء التشغيل أثناء عملية بدء التشغيل. على سبيل المثال، لا تحاول تسجيل رسالة في مسجّل يتم تسجيله أثناء بدء التشغيل. هذه النقطة من عملية التسجيل مبكرة جدًّا بالنسبة لخدماتك حتى تكون متاحة للاستخدام. Configure بعد تشغيل الأسلوب، يستمر وقت تشغيل الوظائف في تسجيل تبعيات أخرى، والتي يمكن أن تؤثر على كيفية عمل خدماتك.

  • تحتفظ حاوية إدراج التبعية بالأنواع المسجلة بوضوح فقط. الخدمات الوحيدة المتوفرة لأنواع قابلة للحقن هي ما تم إعداده في Configure الأسلوب . ولذلك، الأنواع المرتبطة بالوظائف مثل BindingContext وExecutionContext غير متوفرة أثناء الإعداد أو كأنواع قابلة للإدراج.

  • تكوين مصادقة ASP.NET غير مدعوم. يقوم مضيف الوظائف بتكوين خدمات المصادقة ASP.NET لعرض واجهات برمجة التطبيقات بشكل صحيح لعمليات دورة الحياة الأساسية. يمكن أن تتجاوز التكوينات الأخرى في فئة مخصصة Startup هذا التكوين، مما يؤدي إلى عواقب غير مقصودة. على سبيل المثال، يمكن أن يؤدي استدعاء builder.Services.AddAuthentication() إلى قطع المصادقة بين المدخل والمضيف، مما يؤدي إلى رسائل مثل وقت تشغيل Azure Functions غير قابل للوصول.

استخدام التبعيات المدرجة

يتم استخدام إدراج الدالة الإنشائية لجعل التبعيات الخاصة بك متوفرة في دالة. يتطلب استخدام حقن الدالة الإنشائية عدم استخدام فئات ثابتة للخدمات المحقونة أو لفئات الدالات الخاصة بك.

توضح العينة التالية كيفية إدراج التبعيات 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 المطلوبة لتسجيل HttpClient عند بدء التشغيل.

مدة بقاء الخدمة

توفر تطبيقات Azure Functions نفس مدة بقاء الخدمة التي يوفرها إدراج تبعية ASP.NET. بالنسبة لتطبيق الدالات Functions، تسير مدد بقاء الخدمة المختلفة كما يلي:

  • عابرة: يتم إنشاء خدمات عابرة عند كل قرار للخدمة.
  • محددة بنطاق: تطابق مدة بقاء الخدمة المحددة بنطاق مدة تنفيذ الدالة. يتم إنشاء الخدمات المحددة بنطاق مرة واحدة مع كل تنفيذ دالة. تعيد الطلبات اللاحقة لهذه الخدمة أثناء التنفيذ استخدام مثيل الخدمة الموجود.
  • أحادية: تطابق مدة بقاء الخدمة الأحادية مدة بقاء المضيف، ويتم إعادة استخدامها عبر عمليات تنفيذ الدالة على هذا المثيل. يوصى بالخدمات ذات مدة البقاء الأحادية للاتصالات والعملاء، على سبيل المثال، مثيل DocumentClient أو HttpClient.

عرض عينة لمدد بقاء خدمات مختلفة أو تنزيلها على GitHub.

خدمات التسجيل

إذا كنت بحاجة إلى موفر تسجيل خاص بك، سجّل نوعًا مخصصًا كمثيل ILoggerProvider، الذي يتوفر من خلال حزمة NuGet Microsoft.Extensions.Logging.Abstractions.

تتم إضافة Application Insights بواسطة Azure Functions تلقائيًّا.

تحذير

  • لا تقم بإضافة 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

يقوم مضيف الدالة بتسجيل العديد من الخدمات. الخدمات التالية آمنة لاتخاذها تبعية في التطبيق لديك:

نوع الخدمة العمر ‏‏الوصف
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) لإدراجها في دالة.

يتم إدراج عنصر الخيارات في الدالة كمثيل لواجهة 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 أداة Secret Manager تسمح لك بتخزين المعلومات السرية خارج جذر المشروع. وهو ما يقلل احتمالية ارتباط الأسرار عن طريق الخطأ بتحكم المصدر. تقرأ أدوات Azure Functions Core Tools (الإصدار 3.0.3233 أو الأحدث) الأسرار التي ينشئها مدير أسرار ASP.NET Core تلقائيًّا.

لتكوين مشروع Azure Functions في .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.

يمكن الحصول على 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>

الخطوات التالية

لمزيد من المعلومات، راجع الموارد التالية: