翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
C# の Lambda 関数ハンドラー
Lambda 関数ハンドラーは、イベントを処理する関数コード内のメソッドです。関数が呼び出されると、Lambda はハンドラーメソッドを実行します。関数は、ハンドラーが応答を返すか、終了するか、タイムアウトするまで実行されます。
関数が呼び出され、Lambda が関数のハンドラーメソッドを実行すると、関数に 2 つの引数が渡されます。最初の引数は event
オブジェクトです。別の AWS のサービスが関数を呼び出すと、その event
オブジェクトには、関数が呼び出された原因となったイベントに関するデータが含まれます。例えば、API Gateway の event
オブジェクトには、パス、HTTP メソッド、および HTTP ヘッダーに関する情報が含まれています。正確なイベント構造は、関数を呼び出す AWS のサービスによって異なります。個々のサービスのイベント形式の詳細については、「他のサービスで AWS Lambda を使用する」を参照してください。
Lambda は関数に context
オブジェクトも渡します。このオブジェクトには、呼び出し、関数、および実行環境に関する情報が含まれます。詳細については、「C# の AWS Lambda context オブジェクト」を参照してください。
すべての Lambda イベントのネイティブ形式は、JSON 形式のイベントを表すバイトストリームです。関数の入力パラメータと出力パラメータがタイプ System.IO.Stream
でない限り、それらをシリアル化する必要があります。LambdaSerializer
アセンブリ属性を設定して、使用するシリアライザーを指定します。詳細については、「Lambda 関数のシリアル化」を参照してください。
トピック
Lambda 用の .NET 実行モデル
.NET で Lambda 関数を実行するための実行モデルには、クラスライブラリアプローチと実行可能アセンブリアプローチの 2 種類があります。
クラスライブラリアプローチでは、呼び出す関数の AssemblyName
、ClassName
、Method
を示す文字列を Lambda に渡します。この文字列の形式についての詳細は、「クラスライブラリハンドラー」を参照してください。関数の初期化フェーズでは、関数のクラスが初期化され、コンストラクタ内のすべてのコードが実行されます。
実行可能アセンブリアプローチでは、C# 9 の最上位ステートメント
以下のセクションでは、これら 2 つの方法の関数コードの例を示しています。
クラスライブラリハンドラー
次の Lambda 関数コードは、クラスライブラリアプローチを使用する Lambda 関数のハンドラーメソッド (FunctionHandler
) の例を示しています。このサンプル関数では、Lambda は、関数を呼び出すイベントを API Gateway から受信しています。この関数は、データベースからレコードを読み取り、API Gateway レスポンスの一部としてレコードを返します。
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))] namespace GetProductHandler; public class Function { private readonly IDatabaseRepository _repo; public Function() { this._repo = new DatabaseRepository(); } public async Task<APIGatewayProxyResponse> FunctionHandler(APIGatewayProxyRequest request) { var id = request.PathParameters["id"]; var databaseRecord = await this._repo.GetById(id); return new APIGatewayProxyResponse { StatusCode = (int)HttpStatusCode.OK, Body = JsonSerializer.Serialize(databaseRecord) }; } }
Lambda 関数を作成するときは、関数のハンドラーに関する情報をハンドラー文字列の形式で Lambda に提供する必要があります。これにより、関数の呼び出し時に実行するコードのメソッドを Lambda に指示します。C# では、クラスライブラリアプローチを使用する場合のハンドラー文字列の形式は次のようになります。
ASSEMBLY::TYPE::METHOD
。ここで、
-
ASSEMBLY
は、アプリケーションの .NET アセンブリファイルの名前です。Amazon.Lambda.Tools
CLI を使用してアプリケーションを構築し、.csproj ファイルのAssemblyName
プロパティを使用してアセンブリ名を設定しない場合、ASSEMBLY
は単に .csproj ファイルの名前になります。 -
TYPE
は、Namespace
とClassName
からなるハンドラー型の正式名称となります。 -
METHOD
は、コード内の関数ハンドラーメソッドの名前です。
ここに示すコード例では、アセンブリに GetProductHandler
という名前が付けられている場合、ハンドラー文字列は GetProductHandler::GetProductHandler.Function::FunctionHandler
になります。
実行可能アセンブリハンドラー
次の例では、Lambda 関数を実行可能アセンブリとして定義します。このコードのハンドラーメソッドには Handler
という名前が付いています。実行可能アセンブリを使用する場合は、Lambda ランタイムをブートストラップする必要があります。これを行うには、LambdaBootstrapBuilder.Create
メソッドを使用します。このメソッドは、関数がハンドラーとして使用するメソッドと、使用する Lambda シリアライザーを入力として受け取ります。
上位のステートメントの使用の詳細については、AWS コンピューティングブログの「AWS Lambda 用の .NET 6 ランタイムのご紹介
namespace GetProductHandler; IDatabaseRepository repo = new DatabaseRepository(); await LambdaBootstrapBuilder.Create<APIGatewayProxyRequest>(Handler, new DefaultLambdaJsonSerializer()) .Build() .RunAsync(); async Task<APIGatewayProxyResponse> Handler(APIGatewayProxyRequest apigProxyEvent, ILambdaContext context) { var id = input.PathParameters["id"]; var databaseRecord = await this.repo.GetById(id); return new APIGatewayProxyResponse { StatusCode = (int)HttpStatusCode.OK, Body = JsonSerializer.Serialize(databaseRecord) }; };
実行可能アセンブリを使用する場合、コードの実行方法を Lambda に指示するハンドラー文字列はアセンブリの名前です。この例では、GetProductHandler
になります。
Lambda 関数のシリアル化
Lambda 関数が、Stream
オブジェクト以外の入出力タイプを使用する場合は、アプリケーションにシリアル化ライブラリを追加する必要があります。シリアル化は、System.Text.Json
および Newtonsoft.Json
が提供する標準のリフレクションベースのシリアル化を使用するか、ソース生成のシリアル化
ソース生成のシリアル化を使用する
ソース生成のシリアル化は NETバージョン 6 以降の機能で、コンパイル時にシリアル化コードを生成できます。これにより、リフレクションが不要になり、関数のパフォーマンスが向上します。ソース生成のシリアル化を関数で使用するには、以下を実行します。
-
JsonSerializerContext
を継承する新しい部分クラスを作成し、シリアル化または逆シリアル化を必要とするすべての型のJsonSerializable
属性を追加します。 -
LambdaSerializer
を設定してSourceGeneratorLambdaJsonSerializer<T>
を使用します。 -
アプリケーションコード内の手動シリアル化または逆シリアル化をすべて更新して、新しく作成したクラスを使用するようにします。
ソース生成のシリアル化を使用する関数の例を次のコードに示します。
[assembly: LambdaSerializer(typeof(SourceGeneratorLambdaJsonSerializer<CustomSerializer>))] public class Function { private readonly IDatabaseRepository _repo; public Function() { this._repo = new DatabaseRepository(); } public async Task<APIGatewayProxyResponse> FunctionHandler(APIGatewayProxyRequest request) { var id = request.PathParameters["id"]; var databaseRecord = await this._repo.GetById(id); return new APIGatewayProxyResponse { StatusCode = (int)HttpStatusCode.OK, Body = JsonSerializer.Serialize(databaseRecord, CustomSerializer.Default.Product) }; } } [JsonSerializable(typeof(APIGatewayProxyRequest))] [JsonSerializable(typeof(APIGatewayProxyResponse))] [JsonSerializable(typeof(Product))] public partial class CustomSerializer : JsonSerializerContext { }
注記
Lambda でネイティブの事前コンパイル (AOT) を使用する場合は、ソース生成のシリアル化を使用する必要があります。
リフレクションベースのシリアル化を使用する
AWS は、アプリケーションにシリアル化を迅速に追加できる事前構築済みライブラリを提供しています。これは、Amazon.Lambda.Serialization.SystemTextJson
または Amazon.Lambda.Serialization.Json
NuGet パッケージを使用して設定します。背後では、Amazon.Lambda.Serialization.SystemTextJson
は System.Text.Json
を使用してシリアル化タスクを実行し、Amazon.Lambda.Serialization.Json
は Newtonsoft.Json
パッケージを使用します。
ILambdaSerializer
インターフェイスの実装によって独自のシリアル化ライブラリを作成することもできます。これは、Amazon.Lambda.Core
ライブラリの一部として使用できます。このインターフェイスは 2 つのメソッドを定義します。
-
T Deserialize<T>(Stream requestStream);
このメソッドを実装して、
Invoke
API から Lambda 関数ハンドラーに渡されるオブジェクトにリクエストのペイロードを逆シリアル化することができます。 -
T Serialize<T>(T response, Stream responseStream);
このメソッドを実装して、Lambda 関数のハンドラーから返される結果を
Invoke
API オペレーションが返すレスポンスペイロードにシリアル化することができます。
Lambda Annotations Framework による関数コードの簡略化
Lambda Annotations は、.NET 6 と.NET 8 用のフレームワークで、C# を使用して Lambda 関数を簡単に記述できます。Annotations Framework では、通常のプログラミングモデルを使用して記述された Lambda 関数のコードの多くを置き換えることができます。このフレームワークを使用して記述されたコードでは、ビジネスロジックに集中できるより単純な式が使用されます。
次のコード例は、Annotations Framework を使用して Lambda 関数の記述を簡単にする方法を示しています。最初の例は、通常の Lambda プログラムモデルを使用して記述されたコードを示し、2 番目の例は、Annotations Framework を使用した同等のコードを示しています。
public APIGatewayHttpApiV2ProxyResponse LambdaMathAdd(APIGatewayHttpApiV2ProxyRequest request, ILambdaContext context) { if (!request.PathParameters.TryGetValue("x", out var xs)) { return new APIGatewayHttpApiV2ProxyResponse { StatusCode = (int)HttpStatusCode.BadRequest }; } if (!request.PathParameters.TryGetValue("y", out var ys)) { return new APIGatewayHttpApiV2ProxyResponse { StatusCode = (int)HttpStatusCode.BadRequest }; } var x = int.Parse(xs); var y = int.Parse(ys); return new APIGatewayHttpApiV2ProxyResponse { StatusCode = (int)HttpStatusCode.OK, Body = (x + y).ToString(), Headers = new Dictionary≪string, string> { { "Content-Type", "text/plain" } } }; }
[LambdaFunction] [HttpApi(LambdaHttpMethod.Get, "/add/{x}/{y}")] public int Add(int x, int y) { return x + y; }
Lambda Annotations を使用してコードを簡略化する方法を示す別の例については、awsdocs/aws-doc-sdk-examples
GitHub リポジトリにあるこの「cross-service example applicationPamApiAnnotations
は、メイン function.cs
ファイルで Lambda Annotations を使用しています。比較のために、PamApi
フォルダには、通常の Lambda プログラミングモデルを使用して記述された同等のファイルがあります。
Annotations Framework はソースジェネレーター
.NET で Lambda Annotations を使用する方法の詳細については、次のリソースを参照してください。
-
aws/aws-lambda-dotnet
GitHub リポジトリ。 -
AWS 開発者ツールブログの「Introducing .NET Annotations Lambda Framework (Preview)
」。 -
Amazon.Lambda.Annotations
NuGet パッケージ。
Lambda Annotations Framework による依存関係インジェクション
Lambda Annotations Framework を使用して、使い慣れた構文を用いて Lambda 関数に依存関係インジェクションを追加することもできます。[LambdaStartup]
属性を Startup.cs
ファイルに追加すると、Lambda Annotations Framework がコンパイル時に必要なコードを生成します。
[LambdaStartup] public class Startup { public void ConfigureServices(IServiceCollection services) { services.AddSingleton<IDatabaseRepository, DatabaseRepository>(); } }
Lambda 関数は、コンストラクタインジェクションを使用するか、[FromServices]
属性を使用して個々のメソッドに挿入することで、サービスを挿入できます。
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))] namespace GetProductHandler; public class Function { private readonly IDatabaseRepository _repo; public Function(IDatabaseRepository repo) { this._repo = repo; } [LambdaFunction] [HttpApi(LambdaHttpMethod.Get, "/product/{id}")] public async Task<Product> FunctionHandler([FromServices] IDatabaseRepository repository, string id) { return await this._repo.GetById(id); } }
Lambda 関数ハンドラーの制限
ハンドラー署名にはいくつかの制限があることに注意してください。
-
ハンドラーメソッドとその依存関係内で
unsafe
コンテキストを使用できますが、unsafe
ではなく、ハンドラー署名でポインター型を使用する場合があります。詳細については、Microsoft Docs ウェブサイトの「unsafe (C# Reference)」を参照してください。 -
params
キーワードを使用して可変数のパラメータを渡さなかったり、可変数のパラメータをサポートするために使用する入力パラメータまたは戻りパラメータとしてArgIterator
を使用できない場合があります。 -
ハンドラーは、IList<T> Sort<T>(IList<T> input) などの汎用メソッドではない場合があります。
-
async void
署名を持つ Async ハンドラーはサポートされていません。