8

カスタム属性を使用して、フォーム ポスト (支払いゲートウェイ) として投稿するために、クラスのメンバーをプロパティにマップする方法を定義しています。カスタム属性は正常に機能しており、「名前」で属性を取得できますが、メンバー自体で属性を取得したいと考えています。

例えば:

getFieldName("name");

getFieldName(obj.Name);

計画は、メンバーを持つクラスを投稿可能な文字列にシリアル化するメソッドを作成することです。

この時点でのテスト コードは次のとおりです。ret は文字列で、PropertyMapping はカスタム属性です。

foreach (MemberInfo i in (typeof(CustomClass)).GetMember("Name"))
{
    foreach (object at in i.GetCustomAttributes(true))
    {
        PropertyMapping map = at as PropertyMapping;
        if (map != null)
        {
            ret += map.FieldName;
        }
    }
}

前もって感謝します!

4

2 に答える 2

9

C# 3.0 を使用していない限り、実際にはこれを行うことはできません。C# 3.0 を使用している場合は、LINQ (ええと、式ツリー) に依存する必要があります。

あなたがすることは、コンパイラが式ツリーを生成できるようにするラムダ式のダミーメソッドを作成することです(コンパイラは型チェックを行います)。次に、そのツリーを掘り下げてメンバーを取得します。そのようです:

static FieldInfo GetField<TType, TMemberType>(
    Expression<Func<TType, TMemberType>> accessor)
{
    var member = accessor.Body as MemberExpression;
    if (member != null)
    {
        return member.Member as FieldInfo;
    }
    return null; // or throw exception...
}

次のクラスがあるとします。

class MyClass
{
    public int a;
}

次のようにメタデータを取得できます。

// get FieldInfo of member 'a' in class 'MyClass'
var f = GetField((MyClass c) => c.a); 

そのフィールドへの参照を使用して、通常の方法で任意の属性を掘り下げることができます。すなわち反射。

static TAttribute GetAttribute<TAttribute>( 
    this MemberInfo member ) where TAttribute: Attribute
{
    return member.GetCustomAttributes( typeof( TAttribute ), false )
        .Cast<TAttribute>().FirstOrDefault<TAttribute>();
}

これで、コンパイラによって大規模にチェックされるものによって、任意のフィールドの属性を掘り下げることができます。「a」の名前を変更すると、Visual Studioはそれをキャッチします。

var attr = GetField((MyClass c) => c.a).GetAttribute<DisplayNameAttribute>();
Console.WriteLine(attr.DisplayName);

そのコードには単一のリテラル文字列はありません。

于 2009-03-10T14:18:34.757 に答える
4

半分はもう少し簡単にできます。

    foreach (PropertyMapping attrib in
        Attribute.GetCustomAttributes(i, typeof(PropertyMapping)))
    {
        ret += map.FieldName; // whatever you want this to do...
    }

ところで; 属性の最後に という単語を付ける習慣を付ける必要がありますAttribute。これにより重複が発生したとしても ( を参照[XmlAttributeAttribute])。

ただし - 再連載; それは必ずしも些細なことではありません。Json.NET などのシリアライゼーション フレームワークには、かなりの量のコードが含まれています。通常のアプローチは、型コンバーターを取得することですが、多くの点で、これはPropertyDescriptor:

    foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(obj))
    {
        Console.WriteLine("{0}={1}",
            prop.Name, prop.Converter.ConvertToInvariantString(
                prop.GetValue(obj)));
    }
于 2009-03-10T14:16:22.547 に答える