我使用AWS.Net SDK创建了Lambda函数,.net核心版本1.0。我想实现依赖注入。由于lambda函数在AWS环境中独立触发和运行,因此不存在Startup
之类的类。如何以及在哪里可以配置我的容器以实现此实现?
答案 0 :(得分:5)
你可以这样做。您的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
答案 1 :(得分:3)
虽然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;
}
}
答案 2 :(得分:3)
我知道我已经很晚了,但是我添加这个是因为我相信互联网上有一些不好的/不足的例子。 @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
并在完成后将其丢弃。
答案 3 :(得分:1)
如果您正在讨论针对WebAPI的AWS服务的依赖注入,则可以通过dotnet new lambda.AspNetCoreWebAPI
或Visual Studio蓝图使用AspNetCoreWebAPI模板
此模板具有Startup类(当然,每个lambda环境都会执行一次启动,就像您提到的那样)。您在ConfigureServices
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声明配置文件发表评论。