tech.guitarrapc.cóm

Technical updates

Azure FunctionsでC#の拡張メソッドを定義、利用してみた

最近Azure Functionsの記事しか書いてませんが、それぐらいの価値があるサービスなのでAWS Lambda以外にも把握、活用しておくといいともいます。

これまで、C# Script (.csx) をAzure Functionsで利用してきました。利用、CI、外部ライブラリ(NuGet) の利用ときましたが最後に重要な確認があります、拡張メソッドです。

https://tech.guitarrapc.com/entry/2016/04/02/070806

https://tech.guitarrapc.com/entry/2016/04/03/051552

https://tech.guitarrapc.com/entry/2016/04/05/043723

C# で拡張メソッドがどう使えるかは触り心地にとって非常に重要です。そこで今回は拡張メソッドの定義、利用について見てみましょう。

拡張メソッドの利用

拡張メソッドについては、MSDNやC# の鉄板サイトを見ればいいでしょう。拡張メソッドを自前で定義できないことには、やはり結構厳しいものです。

https://ufcpp.net/study/csharp/sp3_extension.html

拡張メソッドの定義方法は、次の通りと紹介されています。

「静的クラス」中に、 第一引数に this キーワードを修飾子として付けた static メソッドを書きます。

つまり以下のようなものです。

static class EnumerableExtensions
{
    public static string ToJoinedString<T>(this IEnumerable<T> source, string separator = "")
    {
        return string.Join(separator, source);
    }
}

今回はこの拡張メソッドをAzure Functionsで定義利用します。

Azure Functions 上で拡張メソッドの定義

さて、単純に上記のコードをAzure Functionsにそのまま持って行ってみます。すると以下のエラーでコンパイルに失敗します。

error CS1109: Extension methods must be defined in a top level static class; EnumerableExtensions is a nested class

これは、Azure Functionsをぱっと見れば分かる通り、表示されていませんがクラスが外側にあるためとわかります。

#r "Newtonsoft.Json"

using System;
using System.Net;
using System.Threading.Tasks;
using Newtonsoft.Json;

public static async Task<object> Run(HttpRequestMessage req, TraceWriter log)
{
    log.Verbose($"Webhook was triggered!");

    string jsonContent = await req.Content.ReadAsStringAsync();
    dynamic data = JsonConvert.DeserializeObject(jsonContent);

    if (data.first == null || data.last == null) {
        return req.CreateResponse(HttpStatusCode.BadRequest, new {
            error = "Please pass first/last properties in the input object"
        });
    }

    return req.CreateResponse(HttpStatusCode.OK, new {
        greeting = $"Hello {data.first} {data.last}!"
    });
}

そして、Azure Functionsはインスタンス化する必要がないので、おそらく静的クラスでしょう。つまり以下のように直接拡張メソッドを定義可能です。

無事にコンパイルされました。

利用もいつもどおりです。

https://gist.github.com/guitarrapc/3fd91076d0a862fcb373760bd11729d6

まとめ

今回のサンプルも載せておきました。

https://github.com/guitarrapc/AzureFunctionsIntroduction

グラニでは、すでに開発の通知周りの多くをAzure Functionsに移行完了しており、すでに本番稼働しています。もちろん複数の手段を保ちつつですが、GitHub WebhookのChatwork通知など多くの処理がAzure Functionsで動いています。通知のほんの少しでも画面に収まらないんですね...。

ちなみにグラニでは、masterブランチへのpush/mergeを起点にGitHub CIされるように組んであります。このため、開発者はAzure Portalに入ることなくVisuals StudioやVS Codeで書いて、push、自動的にデプロイと完結します。

AWS Lambdaが出る前のプレビューから言い続けていたC#サポートはAzureが先に出しました。AWS LambdaはAWSリソース操作など多くの点で活用していますしそれは変わりませんが、C#で何ら変わらず制約もなく普通に書ける良さ、CIが容易であることはとってもいいです。APIGateway + AWS LambdaのFailover先としてのAzure Functionsという使い方もしています。

CIなども含めた総合的な活用しやすさでいうと、AWS Lambdaを上回っています。ただ、API Gateway + AWS Lambdaは別の更なる価値もあったりするので、優劣というより使い方次第です。

現時点では、モニタリングがないため「実行が後から追えない」ものの、現時点では抜けもなく通知されています。

是非皆さんも楽しんでください。