3

属性用に独自のライブラリを構築していますが、プロパティレベルで属性があるかどうかを確認したいと思います。現在、私はうまく機能するこの方法を持っています:

    public static bool HasPropertyAttribute<T>(this object instance, string propertyName)
    {
        return Attribute.GetCustomAttributes(instance.GetType().GetProperty(propertyName), typeof(T), true).Any();
    }

現在、propertyNameとして文字列の代わりにラムダ式を渡すことができるソリューションを検討しています。このメソッドを追加せずにそれを実行して、2つのジェネリック型に依存するようにするエレガントな方法はありますか?

HasPropertyAttribute<T, TProperty>(...).
4

2 に答える 2

6

ラムダ式を使用して、コンパイル時のプロパティ参照を解決できます。(ラムダ式からのプロパティ名の取得から変更されたコード)

public PropertyInfo GetPropertyInfo<TProperty>(
    Expression<Func<TProperty>> propertyLambda)
{
    MemberExpression member = propertyLambda.Body as MemberExpression;
    if (member == null)
        throw new ArgumentException(string.Format(
            "Expression '{0}' refers to a method, not a property.",
            propertyLambda.ToString()));

    PropertyInfo propInfo = member.Member as PropertyInfo;
    if (propInfo == null)
        throw new ArgumentException(string.Format(
            "Expression '{0}' refers to a field, not a property.",
            propertyLambda.ToString()));

    return propInfo;
}

拡張メソッドとして使用する必要はありません (ただし、適応させたい場合は使用できますが、ソース オブジェクト インスタンスは、行を記述する以外は必要ありません)。

public class Test
{
    public string Prop { get; set; }
}

Test t = new Test();
PropertyInfo propInfo = GetPropertyInfo(() => t.Prop);
Console.WriteLine(propInfo.Name + " -> " + propInfo.PropertyType); //Prop -> System.String

編集: 適切な構文が必要で、その型のオブジェクトへの既存の参照を避ける必要がある場合は、次のようにすることができます。

public static class TypedReflection<TSource>
{
    public static PropertyInfo GetPropertyInfo<TProperty>(
        Expression<Func<TSource, TProperty>> propertyLambda)
    {
        MemberExpression member = propertyLambda.Body as MemberExpression;
        if (member == null)
            throw new ArgumentException(string.Format(
                "Expression '{0}' refers to a method, not a property.",
                propertyLambda.ToString()));

        PropertyInfo propInfo = member.Member as PropertyInfo;
        if (propInfo == null)
            throw new ArgumentException(string.Format(
                "Expression '{0}' refers to a field, not a property.",
                propertyLambda.ToString()));

        return propInfo;
    }
}

そして、次のように呼び出します。

PropertyInfo propInfo = TypedReflection<Test>.GetPropertyInfo(o => o.Prop);

この時点で、型指定されたリフレクション メソッド (get メソッド、フィールドなど) を追加するのは非常に簡単です。

EDIT:それはまだ2つのジェネリック型に依存していますが、型推論によって隠されています。私は 2 番目の例を好みます。最低限、宣言するクラスの型を指定する必要がありますが (型の安全性が必要なため)、オブジェクト インスタンスは必要ありません。また、プロパティの名前を変更すると、このコードに伝播され、PropertyInfo.

于 2012-10-25T16:11:59.810 に答える
0

私はこのソリューションを選択しました。すべての中で最も少ないコードです。

    public static bool HasPropertyAttribute<T, TProperty>(this T instance, Expression<Func<T, TProperty>> propertySelector, Type attribute)
    {
        return Attribute.GetCustomAttributes(instance.GetType().GetProperty((propertySelector.Body as MemberExpression).Member.Name), attribute, true).Any();
    }

次のように呼び出されます。

var cc = new CustomClass();
cc.HasPropertyAttribute(x => x.Name, typeof(NullableAttribute))
于 2012-10-25T16:29:42.810 に答える