今年は非常にうれしいことがAzureとAWS両方でありました。Azure Functionsと .NET Core on AWS Lambdaです。 これまで多くのAWS Lambda関数 (Node.js) とAzure Functions (C#) を書いてきましたがこれでようやくAWS Lambdaに寄せられます。
早速AWS LambdaでC# (.NET Core) を触ってみましょう。
Lambda 上は Java と同じく dll をアップロード
Nodeと違い、Java同様のdllをzipで固めてアップロードとなります。そのため、Lambdaの画面でコードを直接触ることはできません。

ここはAzure Functionsと違い直接コード修正にはなりませんね。ただし大事なのは、.NET Coreをビルドした結果を挙げるという点です。Azure Functionsですぐに出会って今でも困るのが、「共通コードを参照した場合にローカルビルドを通せなくなるケース」や「.csxのためインテリセンスが非常に貧弱」という問題があります。*1
DLLをビルドしてアップロードということは、ローカル挙動が安定して、コンパイル、ビルドも安定するので個人的には十分に許容、嬉しいポインとのです。*2
C# (.NET Core) でコードを書いてみる
記事作成の現時点ではAWS Documentがないので、手探りで見てみましょう。ドキュメントが公開されたので参考にどうぞ。
https://aws.amazon.com/jp/blogs/compute/announcing-c-sharp-support-for-aws-lambda/
https://docs.aws.amazon.com/lambda/latest/dg/dotnet-programming-model-handler-types.html
環境はWindows 10 Pro + Visual Studio 2015 Enterpriseです。
.NET Core 環境を用意する
まずは .NET Coreの最新版をインストールします。手順通りにやっていきましょう。
https://www.microsoft.com/net/core#Windowsvs2015
インストール中。

5分前後かかります。

Visual Studio Integration
AWSはVisual Studio Integrationがかなり進んでいます。リソース管理にとどまらず、Node.jsのLambda関数も書いています。
LambdaをC# (.NET Core) でVisual Studioで書くため、最新版のAWS SDK for .NETをダウンロード、インストールしましょう。インストール後に新規プロジェクト > Templates > Visual C# > AWS Lambdaというのが新しくできています。
4つプロジェクトがありますが、今回はシンプルに関数を作ってローカルビルド > アップロードという流れでやるため「AWS Lambda Project (.NET Core)」を使ってみましょう。
| プロジェクト種別 | 説明 |
|---|---|
| AWS Lambda Project (.NET Core) | A project for creating a AWS Lambda Functions using .NET Core |
| AWS Lambda Project with Tests (.NET Core) | A project for creating a AWS Lambda Functions using .NET Core |
| AWS Serverless Project (.NET Core) | An AWS Serverless application uses the power of AWS Lmabda and AWS CloudFormation to build a cloud-enabled serverless application |
| AWS Serverless Project with Tests (.NET Core) | An AWS Serverless application uses the power of AWS Lmabda and AWS CloudFormation to build a cloud-enabled serverless application |

BluePrint の選択
4つのひな形が提示されています。今回は単純なEmpty Functionを作ってみます。

余談ですが、もし.NET Coreのセットアップを忘れて、AWS Lambda Projectを作ろうとすると次のエラーが出て作れないので注意です。この場合、前述した.NET Coreの最新をインストールしてから、再度Lambdaプロジェクトを作ってみましょう。

もしも project.json のパッケージ復元でエラーが生じる場合
AWS Lambda (.NET Core) のプロジェクトを作ってproject.jsonでエラーが出ることもあるようです。*3
この場合、Amazon* とつくパッケージが解決できていない場合は、直接nugetパッケージをインストールすればokです。例えば次のproject.jsonならdotnet restoreでパッケージを復元しましょう。*4
{
"version": "1.0.0-*",
"buildOptions": {
},
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.1"
},
"Amazon.Lambda.Core": "1.0.0",
"Amazon.Lambda.Serialization.Json": "1.0.0",
"Amazon.Lambda.Tools": "1.0.0-preview1"
},
"tools": {
"Amazon.Lambda.Tools": "1.0.0-preview1"
},
"frameworks": {
"netcoreapp1.0": {
"imports": "dnxcore50"
}
}
}
このコマンドをPackage Management Consoleで実行でもパッケージは復元できます。*5
Install-Package Amazon.Lambda.Tools -Pre Install-Package Amazon.Lambda.Core Install-Package Amazon.Lambda.Serialization.Json
解決されれば、project.jsonのエラーが消えて、Function.csもエラーが出ていないはずです。


この状態で何も編集せずビルドが通れば準備完了です。

サンプルコードの記述
雑にConsole.WriteLineだけ追加してちょっとだけいじってみます。
> https://gist.github.com/guitarrapc/e21578a8c777993e97dae62e7f03ac8e
アップロード
残念ながら今日発表されたCodeBuildはC#をサポートしていません。
Build Environment – Language / runtime environment (Android, Java, Python, Ruby, Go, Node.js, or Docker).
https://aws.amazon.com/jp/blogs/aws/aws-codebuild-fully-managed-build-service/
CIのことは次回以降にして、ローカルでビルドしてアップロードしてみましょう。
Node.jsと同様に、「アップロードする対象のプロジェクトを右クリック -> Publish to AWS Lambda」します。

資格情報などをいい感じにして

IAM Roleに必要な権限のロールを割り当てます。今回はただの実行なのでlambda_exec_roleでokです。

メモリはデフォルトのままで行きますが、Javaと似た傾向だと予想します。性能に関しても後日確認してみましょう。
https://acro-engineer.hatenablog.com/entry/2016/08/02/120000
ではUploadしてみてください。うまくいくと、Lambdaの画面をAWS Consoleを開かずにVSでFunction画面が開いてくれます。Event Sourceなどもここにあるので、事実上のローカルからの直接実行です。

実行
そのままVisula StudioからInvokeするか、AWS Consoleで実行してみましょう。
このとき、Node.jsの時のようにjsonでイベントを記述すると自動的にデシリアライズされてしまいエラーが発生してしまいます。
{
"errorType": "JsonReaderException",
"errorMessage": "Unexpected character encountered while parsing value: {. Path '', line 1, position 1.",
"stackTrace": [
"at Newtonsoft.Json.JsonTextReader.ReadStringValue(ReadType readType)",
"at Newtonsoft.Json.JsonTextReader.ReadAsString()",
"at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadForType(JsonReader reader, JsonContract contract, Boolean hasConverter)",
"at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)",
"at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)",
"at Newtonsoft.Json.JsonSerializer.Deserialize[T](JsonReader reader)",
"at lambda_method(Closure , Stream , Stream , ContextInfo )"
]
}
今回は、受ける引数をstringとしているので、"hogemoge" というストリングを送るようにします。うまくResponseにかえって来ましたね。

任意のクラスを受けて実行する
次はstringではなく任意のクラスを用意して、外部から来たJSONを受けられるようにします。
想定するJSONは次のフォーマットです。
{"Str":"hogehoge","StrArray":["hoge","huga","foo"]}
対応するクラスは次の通りです。
public class SampleClass { public string Str { get; set; } public string[] StrArray { get; set; } }
ということで全体
https://gist.github.com/guitarrapc/e6cae2690cf85cd81c391f18717df7b0
実行してみるとうまく取れていますね。

まとめ
まずはHello Worldでした。次はAzure Functionsで書いた処理をサクサクLambdaにもってきて紹介します。
今回の実装を含めて、AWS Lambda .NET Core (C#) の実装サンプルはリポジトリにあげていくのでよろしければどうぞ。