[英]How to use Dependency Injection in AWS Lambda C# implementation
我使用 AWS.Net SDK、.net 核心版本 1.0 創建了 Lambda 函數。 我想實現依賴注入。 由於 lambda 函數在 AWS 環境中觸發並獨立運行,因此不存在像Startup
這樣的 class。 如何以及在何處配置我的容器以實現此實現?
我知道我來晚了,但我添加這個是因為我相信 inte.net 上有一些不好的/缺少的例子。 @Erndob 關於已接受的答案是正確的。 您只會創建更多實例。
根據您在 DI 容器中進行的注冊,您需要牢記:
結束了這樣的事情:
public class Function
{
private ServiceCollection _serviceCollection;
public Function()
{
ConfigureServices();
}
public string FunctionHandler(string input, ILambdaContext context)
{
using (ServiceProvider serviceProvider = _serviceCollection.BuildServiceProvider())
{
// entry to run app.
return serviceProvider.GetService<App>().Run(input);
}
}
private void ConfigureServices()
{
// add dependencies here
_serviceCollection = new ServiceCollection();
_serviceCollection.AddTransient<App>();
}
}
使用此模式,每個 lambda 調用都將獲得一個新的ServiceProvider
並在完成后將其處理掉。
你可以這樣做。 您的FunctionHandler是您的應用程序的入口點。因此您必須從那里連接服務集合。
public class Function
{
public string FunctionHandler(string input, ILambdaContext context)
{
var serviceCollection = new ServiceCollection();
ConfigureServices(serviceCollection);
// create service provider
var serviceProvider = serviceCollection.BuildServiceProvider();
// entry to run app.
return serviceProvider.GetService<App>().Run(input);
}
private static void ConfigureServices(IServiceCollection serviceCollection)
{
// add dependencies here
// here is where you're adding the actual application logic to the collection
serviceCollection.AddTransient<App>();
}
}
public class App
{
// if you put a constructor here with arguments that are wired up in your services collection, they will be injected.
public string Run(string input)
{
return "This is a test";
}
}
如果您想連接日志記錄,請查看: https : //github.com/aws/aws-lambda-dotnet/tree/master/Libraries/src/Amazon.Lambda.Logging.AspNetCore
使用常規的 Lambda 項目模板,Scoped lifetime app 似乎不存在,您必須按照上面的答案創建解決方法。
借助新的“.NET Annotations Lambda Framework”,AWS 正試圖解決該問題。
這里的解釋: https://aws.amazon.com/blogs/developer/introducing.net-annotations-lambda-framework-preview/
雖然FunctionHandler確實是您的應用程序的入口點,但我實際上會在無參數構造函數中連接您的DI。 構造函數只被調用一次,所以這個純粹的“設置”代碼實際上只需要調用一次。 我們只想在每次后續調用中使用它,並將其路由到同一個容器。
public class Function
{
private static ServiceProvider ServiceProvider { get; set; }
/// <summary>
/// The parameterless constructor is what Lambda uses to construct your instance the first time.
/// It will only ever be called once for the lifetime of the container that it's running on.
/// We want to build our ServiceProvider once, and then use the same provider in all subsequent
/// Lambda invocations. This makes things like using local MemoryCache techniques viable (Just
/// remember that you can never count on a locally cached item to be there!)
/// </summary>
public Function()
{
var services = new ServiceCollection();
ConfigureServices(services);
ServiceProvider = services.BuildServiceProvider();
}
public async Task FunctionHandler(SQSEvent evnt, ILambdaContext context)
{
await ServiceProvider.GetService<App>().Run(evnt);
}
/// <summary>
/// Configure whatever dependency injection you like here
/// </summary>
/// <param name="services"></param>
private static void ConfigureServices(IServiceCollection services)
{
// add dependencies here ex: Logging, IMemoryCache, Interface mapping to concrete class, etc...
// add a hook to your class that will actually do the application logic
services.AddTransient<App>();
}
/// <summary>
/// Since we don't want to dispose of the ServiceProvider in the FunctionHandler, we will
/// at least try to clean up after ourselves in the destructor for the class.
/// </summary>
~Function()
{
ServiceProvider.Dispose();
}
}
public class App
{
public async Task Run(SQSEvent evnt)
{
// actual business logic goes here
await Task.CompletedTask;
}
}
這是另一種處理方法。 這是此處https://aws.amazon.com/blogs/compute/migrating-a-monolithic.net-rest-api-to-aws-lambda/中一些代碼的簡化版本。 一個顯着的區別是BuildServiceProvider()
僅在創建 Lambda 時調用一次。
public class Function
{
private static IServiceProvider services;
private readonly IBookingRepository bookingRepository;
private readonly ILogger<Function> logger;
public Function()
{
ConfigureServices();
this.bookingRepository = services.GetRequiredService<IBookingRepository>();
this.logger = services.GetRequiredService<ILogger<Function>>();
}
public async Task<APIGatewayProxyResponse> FunctionHandler(APIGatewayProxyRequest apigProxyEvent, ILambdaContext context)
{
if (!apigProxyEvent.PathParameters.ContainsKey("customerId"))
{
return new APIGatewayProxyResponse
{
StatusCode = 400,
Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } }
};
}
var customerId = apigProxyEvent.PathParameters["customerId"];
this.logger.LogInformation($"Received request to list bookings for: {customerId}");
var customerBookings = await this.bookingRepository.ListForCustomer(customerId);
return new APIGatewayProxyResponse
{
Body = JsonSerializer.Serialize(customerBookings),
StatusCode = 200,
Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } }
};
}
private void ConfigureServices()
{
// Add dependencies here.
var serviceCollection = new ServiceCollection();
serviceCollection.AddDbContext<BookingContext>(options =>
options.UseMySQL("ConnectionString..."));
serviceCollection.AddTransient<IBookingRepository, BookingRepository>();
serviceCollection.AddLogging(logging =>
{
logging.AddLambdaLogger();
logging.SetMinimumLevel(LogLevel.Debug);
});
services = serviceCollection.BuildServiceProvider();
}
}
如果您正在討論針對WebAPI的AWS服務的依賴注入,則可以通過dotnet new lambda.AspNetCoreWebAPI
使用AspNetCoreWebAPI模板獲得dotnet new lambda.AspNetCoreWebAPI
或Visual Studio藍圖
這個模板有Startup類(當然每個lambda環境都會執行一次啟動,就像你提到的那樣)。 您在ConfigureServices
添加了添加AWS服務
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddDefaultAWSOptions(Configuration.GetAWSOptions());
// Add service to obtain in Controllers constructor
services.AddAWSService<IAmazonDynamoDB>();
}
然后使用構造函數為Controller類注入依賴項
IAmazonDynamoDB client;
public ValuesController(IAmazonDynamoDB dbClient)
{
this.client = dbClient;
}
這些服務是從使用環境變量檢索的憑據啟動的,因此請確保將您的AWS配置文件包含在appsettings.json中。 如果您不確定appsettings.json或如何根據ASPNETCORE_ENVIRONMENT聲明配置文件發表評論。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.