web-dev-qa-db-ja.com

ラムダ式を使用してプロパティ名とタイプを取得する

以下のような構文を使用して、プロパティの名前と型を取得する関数を記述しようとしています。

private class SomeClass
{
    Public string Col1;
}

PropertyMapper<Somewhere> propertyMapper = new PropertyMapper<Somewhere>();
propertyMapper.MapProperty(x => x.Col1)

この構文に大きな変更を加えずにプロパティを関数に渡す方法はありますか?

プロパティ名とタイプを取得したいのですが。

以下の例では、取得したいと思います

Name = "Col1"およびType = "System.String"

誰か助けてもらえますか?

37
pythonandchips

Expressions を使用してプロパティまたはフィールドの名前を取得し、使用を開始する例を以下に示します。

public static MemberInfo GetMemberInfo<T, U>(Expression<Func<T, U>> expression)
{
    var member = expression.Body as MemberExpression;
    if (member != null)
        return member.Member;

    throw new ArgumentException("Expression is not a member access", "expression");
}

呼び出しコードは次のようになります。

public class Program
{
    public string Name
    {
        get { return "My Program"; }
    }

    static void Main()
    {
        MemberInfo member = ReflectionUtility.GetMemberInfo((Program p) => p.Name);
        Console.WriteLine(member.Name);
    }
}

ただし、注意が必要です。単純な(Program p) => p.Name実際にはかなりの作業が含まれます(測定可能な時間がかかる場合があります)。メソッドを頻繁に呼び出すのではなく、結果をキャッシュすることを検討してください。

60
Jacob Carpenter

これをここに置いて、以前のアプローチに基づいて構築すると思いました。

public static class Helpers
{
    public static string PropertyName<T>(Expression<Func<T>> expression)
    {
        var member = expression.Body as MemberExpression;
        if (member != null && member.Member is PropertyInfo)
            return member.Member.Name;

        throw new ArgumentException("Expression is not a Property", "expression");
    }
}

その後、次のように呼び出すことができます。

Helpers.PropertyName(() => TestModel.TestProperty);

また、VS 2015とC#6.0では単純にnameofを使用できることも指摘しておきます。

https://msdn.Microsoft.com/en-us/library/dn986596.aspx

3
TheRock

これはとても重宝しました。

public class PropertyMapper<T>
{
    public virtual PropertyInfo PropertyInfo<U>(Expression<Func<T, U>> expression)
    {
        var member = expression.Body as MemberExpression;
        if (member != null && member.Member is PropertyInfo)
            return member.Member as PropertyInfo;

        throw new ArgumentException("Expression is not a Property", "expression");
    }

    public virtual string PropertyName<U>(Expression<Func<T, U>> expression)
    {
        return PropertyInfo<U>(expression).Name;
    }

    public virtual Type PropertyType<U>(Expression<Func<T, U>> expression)
    {
        return PropertyInfo<U>(expression).PropertyType;
    }
}

私はこの小さなクラスを元の要求に従うために作りました。プロパティの名前が必要な場合は、次のように使用できます。

PropertyMapper<SomeClass> propertyMapper = new PropertyMapper<SomeClass>();
string name = propertyMapper.PropertyName(x => x.Col1);
3
chapacool

これは、C#6で簡単に実行できます。プロパティの名前を取得するには、nameof演算子を使用します。

nameof(User.UserId)

プロパティのタイプを取得するには、typeof演算子を使用します。

typeof(User.UserId)
3
Anand Patel