プログラミング C# - 翔ソフトウェア (Sho's)

C#/.NET/ソフトウェア開発など

Expression を使ってラムダ式のメンバー名を取得する

Expression

前回「Expression の構造を調べてみる」と云う記事で、Expression の内部のツリー構造を調べた。

その中で、ラムダ式を Expression として扱うことで、式の中の名前が取れることが判った。

今回は これを利用してラムダ式のメンバー名を取得する例を挙げてみたい。

ラムダ式のメンバー名を取得する例

先ずシンプルなクラスを一つ用意する。

class Item
{
    public int Id { get; set; }
}

そして、item => item.Id というラムダ式を渡してプロパティ名を取得するメソッドを作ってみよう。

前回の知識が役に立つ。

前回の調査で、ラムダ式の => の右側の式は Body で取れることが解かっている。

次に、Visual Studio のデバッガーなどを駆使して、Body の式の種類を調べよう。Body は MemberExpression であることが判る筈だ。

MemberExpression であれば、プロパティの内の Member の Name で名前が取得できる。

実際にメソッドを作ってみるとこんな感じだ:

using System;
using System.Linq.Expressions;

public static class ObjectExtensions
{
    // Expression からメンバー名を取得
    public static string GetMemberName<ObjectType, MemberType>(this ObjectType @this, Expression<Func<ObjectType, MemberType>> expression)
    {
        return ((MemberExpression)expression.Body).Member.Name;
    }
}

早速使ってみよう。

using System;

class Item
{
    public int Id { get; set; }
}

class Program
{
    static void Test()
    {
        var memberName = new Item().GetMemberName(item => item.Id);
        Console.WriteLine(memberName);
    }

    public static void Main()
    {
        Test();
    }
}

実行結果は下の通りで、ラムダ式からプロパティ名が取得できた。

Id

次に、Item クラスの内部からもやってみよう。

今度のラムダ式は () => Id だ。

ObjectExtensions クラスに先程作ったメソッドから第一引数を無くしたメソッドを追加して、

using System;
using System.Linq.Expressions;

public static class ObjectExtensions
{
    // Expression からメンバー名を取得
    public static string GetMemberName<ObjectType, MemberType>(this ObjectType @this, Expression<Func<ObjectType, MemberType>> expression)
    {
        return ((MemberExpression)expression.Body).Member.Name;
    }

    // Expression からメンバー名を取得
    public static string GetMemberName<MemberType>(Expression<Func<MemberType>> expression)
    {
        return ((MemberExpression)expression.Body).Member.Name;
    }
}

Item クラス内部に Test 用のメソッドを追加し、そこから呼んでみる。

using System;

class Item
{
    public int Id { get; set; }

    public void Test()
    {
        var memberName = ObjectExtensions.GetMemberName(() => Id);
        Console.WriteLine(memberName);
    }
}

class Program
{
    static void Test()
    {
        var memberName = new Item().GetMemberName(item => item.Id);
        Console.WriteLine(memberName);
    }

    public static void Main()
    {
        Test();
        new Item().Test();
    }
}

実行結果は下の通り。クラス内部からもラムダ式からプロパティ名が取得できた。

Id
Id

■ 今回のまとめ

Expression を利用してラムダ式のメンバー名を取得してみた。

しかし、こんなことが何の役に立つのだろうか?

次回から、これを利用した応用例について書こうと思う。