依赖注入是一种设计模式,它允许开发者编写松耦合的代码。这是通过在运行时指定类需要的对象,而不是实现具体的依赖来实现的。通过在应用程序中使用依赖注入,可以确保代码库是可维护的、可测试的,并且易于更新。
微软最近发布了Microsoft.Azure.Functions.Extensions NuGet包(截至撰写本文时版本为1.0.0)。此包通过构建在现有的ASP.NET Core依赖注入特性之上,为依赖注入提供了原生支持。本文将使用此包在简单的REST触发器C#函数中实现DI。
可以通过Visual Studio或使用Azure Function CLI来创建HTTP函数。要使用Azure Function CLI,需要安装Azure Functions Core Tools,可以通过npm安装。
npm i -g azure-functions-core-tools --unsafe-perm true
首先,需要创建函数项目:
func init <PROJECT NAME> --worker-runtime dotnet
然后切换到新创建的项目目录,并运行以下命令创建函数:
func new --name <FUNCTION NAME> --template "HttpTrigger"
创建项目后,需要添加对Microsoft.Azure.Functions.Extensions包的引用,并更新到函数SDK的最新版本。可以使用dotnet CLI来完成。
dotnet add package Microsoft.Azure.Functions.Extensions
dotnet add package Microsoft.NET.Sdk.Functions
接下来,将创建将注入到函数中的服务。在本例中,将使用一个简单的类,它返回一个问候消息。在函数项目中创建以下文件(IGreeter.cs和Greeter.cs)。
namespace DependencyInjectionTutorial
{
public interface IGreeter
{
string Greet();
}
}
namespace DependencyInjectionTutorial
{
public class Greeter : IGreeter
{
public string Greet()
{
return "Greetings from Greeter!";
}
}
}
接下来,需要设置Startup类,它将用于在应用程序中注册服务。注册服务时,可以选择三种主要的服务生命周期。
短暂 - 每次从服务容器请求时都会创建服务的实例。这适用于轻量级、无状态的服务。
作用域 - 每个客户端请求(连接)创建一次服务。
单例 - 第一次请求时创建单例服务,然后每个后续请求都使用相同的实例。
为了本例的目的,将使用短暂的服务生命周期,因为想在每次调用函数时都创建一个Greeter的实例。
using DependencyInjectionTutorial;
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
[assembly: FunctionsStartup(typeof(Startup))]
namespace DependencyInjectionTutorial
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddTransient<IGreeter, Greeter>();
}
}
}
最后,需要修改HTTP函数以使用Greeter服务,通过构造函数注入,这意味着还需要将函数转换为非静态的。
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
namespace DependencyInjectionTutorial
{
public class DependencyInjectionTutorialFunction
{
private readonly IGreeter _greeter;
public DependencyInjectionTutorialFunction(IGreeter greeter)
{
_greeter = greeter;
}
[FunctionName("DependencyInjectionTutorialFunction")]
public IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req, ILogger log)
{
var greeting = _greeter.Greet();
log.LogInformation($"Got Greeting: {greeting}");
return new OkObjectResult(greeting);
}
}
}
要测试函数,请使用函数CLI运行以下命令,并在终端提供的链接中导航到浏览器。
func host start
如果看到了“Greetings from Greeter!”的消息,那么这意味着服务依赖注入已正确配置。干得好!