1. ホーム
  2. c#

[解決済み】プロパティの名前を文字列で取得する

2022-04-03 20:50:54

質問

(受理した回答を使って作成した以下の解答をご覧ください。)

私は、リフレクションを含むいくつかのコードの保守性を改善しようとしています。このアプリには、.NET Remotingインターフェースがあり、(とりわけ) Execute 公開されているリモートインターフェイスに含まれていないアプリの部分にアクセスするためのものです。

以下は、アプリがExecute経由でアクセスすることを意図したプロパティ(この例では静的なもの)を指定する方法です。

RemoteMgr.ExposeProperty("SomeSecret", typeof(SomeClass), "SomeProperty");

だから、リモート・ユーザーが呼び出すことができる。

string response = remoteObject.Execute("SomeSecret");

で、アプリはリフレクションを使って SomeClass.SomeProperty を見つけ、その値を文字列として返します。

残念ながら、誰かがSomePropertyの名前を変えて、ExposeProperty()の3番目のparmを変更し忘れると、このメカニズムが壊れてしまいます。

に相当するものが必要なんです。

SomeClass.SomeProperty.GetTheNameOfThisPropertyAsAString()

の3番目のparmとして使用します。 ExposeProperty リファクタリングツールがリネームの面倒をみてくれるからです。

このような方法はあるのでしょうか?

さて、私が最終的に作成したものは以下の通りです(私が選択した回答と彼が参照した質問をもとに)。

// <summary>
// Get the name of a static or instance property from a property access lambda.
// </summary>
// <typeparam name="T">Type of the property</typeparam>
// <param name="propertyLambda">lambda expression of the form: '() => Class.Property' or '() => object.Property'</param>
// <returns>The name of the property</returns>
public string GetPropertyName<T>(Expression<Func<T>> propertyLambda)
{
    var me = propertyLambda.Body as MemberExpression;

    if (me == null)
    {
        throw new ArgumentException("You must pass a lambda of the form: '() => Class.Property' or '() => object.Property'");
    }

    return me.Member.Name;
 }

使用方法

// Static Property
string name = GetPropertyName(() => SomeClass.SomeProperty);

// Instance Property
string name = GetPropertyName(() => someObject.SomeProperty);

さて、このクールな機能を使って、ExposePropertyメソッドを簡略化する時がやってきました。ドアノブを磨くのは危険な作業です...。

どのように解決する?

ここからGetMemberInfoを使用します。 ラムダ式からプロパティ名を取得する というようなことができます。

RemoteMgr.ExposeProperty(() => SomeClass.SomeProperty)

public class SomeClass
{
    public static string SomeProperty
    {
        get { return "Foo"; }
    }
}

public class RemoteMgr
{
    public static void ExposeProperty<T>(Expression<Func<T>> property)
    {
        var expression = GetMemberInfo(property);
        string path = string.Concat(expression.Member.DeclaringType.FullName,
            ".", expression.Member.Name);
        // Do ExposeProperty work here...
    }
}

public class Program
{
    public static void Main()
    {
        RemoteMgr.ExposeProperty("SomeSecret", () => SomeClass.SomeProperty);
    }
}