AWS.Net SDK、.net coreバージョン1.0を使用してLambda関数を作成しました。依存性注入を実装したい。ラムダ関数はAWS環境で独立してトリガーおよび実行されるため、Startup
のようなクラスは存在しません。この実装を実現するためにコンテナをどこでどのように構成できますか?
あなたはこれを行うことができます。 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 =
私はゲームにかなり遅れていることを知っていますが、インターネットには悪い例や欠けている例があると思うので、これを追加します。 @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>();
}
}
このパターンを使用すると、ラムダを呼び出すたびに新しいServiceProvider
が取得され、終了時に破棄されます。
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;
}
}
AWS Services for WebAPIの依存性注入について話している場合、dotnet new lambda.AspNetCoreWebAPI
またはVisual Studioブループリントを介してAspNetCoreWebAPIテンプレートを使用することが可能です。
このテンプレートにはスタートアップクラスがあります(もちろん、各スタートアップは、前述のようにラムダ環境ごとに1回実行されます)。 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に従ってプロファイルを宣言する方法がわからない場合は、コメントを残してください。