在 .NET Azure Functions 中使用相依性插入
Azure Functions 支援相依性插入 (DI) 軟體設計模式,這是在類別及其相依性之間達成控制反轉 (IoC) 的技術。
Azure Functions 中的相依性插入是以 .NET Core 相依性插入功能為基礎。 建議熟悉 .NET Core 相依性插入 (機器翻譯)。 您覆寫相依性的方式,與在取用方案上使用 Azure Functions 讀取設定值的方式有所不同。
從 Azure Functions 2.x 開始支援相依性插入。
重要
本文中的指引僅適用於與執行階段在同處理序執行的 C# 類別庫函式。 此自訂相依性插入模型不適用於 .NET 隔離的函式,這可讓您在跨處理序執行 .NET 函式。 .NET 隔離背景工作處理序模型依賴一般 ASP.NET Core 相依性插入模式。 若要深入了解,請參閱 .NET 隔離背景工作處理序指南中的相依性插入。
必要條件
您必須安裝下列 NuGet 套件,才能使用相依性插入:
Microsoft.NET.Sdk.Functions 套件 1.0.28 版或更新版本
Microsoft.Extensions.DependencyInjection (目前僅支援 2.x 版或更新版本)
註冊伺服器
若要註冊服務,請建立方法來設定元件並將其新增至 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>();
}
}
此範例會使用在啟動時註冊 HttpClient
所需的 Microsoft.Extensions.Http 套件。
警示
在執行階段處理啟動類別的前後會執行一系列註冊步驟。 因此,請記住下列項目:
啟動類別僅適用於設定和註冊。 避免使用啟動時在啟動程序期間註冊的服務。 例如,請勿嘗試在啟動期間註冊的記錄器中記錄訊息。 註冊程序的這個時間點太早,還無法提供服務使用。 執行
Configure
方法之後,Functions 執行階段會繼續註冊其他相依性,這可能會影響服務的運作方式。相依性插入容器只會保留明確註冊的類型。 唯一做為可插入類型使用的服務是設定在
Configure
方法中的服務。 因此,Function 特定類型 (例如BindingContext
和ExecutionContext
) 無法在設定期間使用或作為可插入的類型使用。不支援設定 ASP.NET 驗證。 Functions 主機會設定 ASP.NET 驗證服務,以正確地公開核心生命週期作業的 API。 在自訂
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.");
}
}
此範例會使用在啟動時註冊 HttpClient
所需的 Microsoft.Extensions.Http 套件。
執行個體存留期
Azure Functions 應用程式提供與 ASP.NET 相依性插入相同的服務存留期。 針對 Functions 應用程式,不同服務存留期的行為如下所示:
- 暫時性:暫時性服務會在每次服務解析時建立。
- 有限範圍:有限範圍的服務存留期符合函式執行存留期。 限域服務會在每次執行函式後建立。 稍後在執行期間對該服務提出的要求會重複使用現有服務執行個體。
- singleton:singleton 服務存留期符合主機存留期,而且在該執行個體上跨函式執行重複使用。 建議連線和用戶端使用單一存留期服務,例如
DocumentClient
或HttpClient
執行個體。
請前往 GitHub 檢視或下載不同服務存留期的範本。
記錄服務
如果您需要自己的記錄提供者,請將自訂類型註冊為 ILoggerProvider
的執行個體,可透過 Microsoft.Extensions.Logging.Abstractions NuGet 套件取得。
Azure Functions 會自動新增 Application Insights。
警告
- 請勿將
AddApplicationInsightsTelemetry()
新增至服務集合,因為這會註冊與環境所提供服務衝突的服務。 - 若您使用的是內建 Application Insights 功能,請勿註冊自己的
TelemetryConfiguration
或TelemetryClient
。 如果需要設定自己的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"
}
}
}
如需記錄層級的詳細資訊,請參閱設定記錄層級。
函數應用程式提供的服務
函式主機會註冊許多服務。 下列服務可安全地作為應用程式中的相依性:
服務類型 | 存留期 | 描述 |
---|---|---|
Microsoft.Extensions.Configuration.IConfiguration |
單一 | 執行階段設定 |
Microsoft.Azure.WebJobs.Host.Executors.IHostIdProvider |
單一 | 負責提供主機執行個體的識別碼 |
如有其他要相依的服務,請在 GitHub 上建立並張貼問題。
覆寫主機服務
目前不支援覆寫主機所提供的服務。 如有要覆寫的服務,請在 GitHub 上建立並張貼問題。
使用選項和設定
應用程式設定中定義的值位於 IConfiguration
執行個體中,其可供讀取啟動類別中的應用程式設定值。
您可將值從 IConfiguration
執行個體擷取到自訂類型中。 將應用程式設定值複製到自訂類型會使這些值得以插入,以供輕鬆地測試服務。 讀入設定執行個體的設定必須是簡單的索引鍵/值組。 針對在彈性進階方案中執行的函式,應用程式設定名稱只能包含字母、數字 (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 會提供祕密管理員工具,讓您可以將祕密資訊儲存在專案根目錄之外。 此工具降低了祕密被意外提交至原始檔控制的可能性。 Azure Functions Core Tools (3.0.3233 版或更新版本) 會自動讀取 ASP.NET Core 祕密管理員所建立的祕密。
若要將 .NET Azure Functions 專案設定為使用使用者祕密,請在專案根目錄中執行下列命令。
dotnet user-secrets init
然後使用 dotnet user-secrets set
命令來建立或更新祕密。
dotnet user-secrets set MySecret "my secret value"
若要存取函數應用程式程式碼中的使用者祕密值,請使用 IConfiguration
或 IOptions
。
自訂設定來源
若要指定其他設定來源,請覆寫函式應用程式 StartUp
類別中的 ConfigureAppConfiguration
方法。
下列範例從基本與選擇性環境特定應用程式設定檔中新增設定值。
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)
{
}
}
將設定提供者新增至 IFunctionsConfigurationBuilder
的 ConfigurationBuilder
屬性。 如需使用設定提供者的詳細資訊,請參閱 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>
下一步
如需詳細資訊,請參閱以下資源: