web-dev-qa-db-ja.com

抽象プロパティのカスタム属性の継承

HTMLでアイテムを表示するときにユーザーが表示する必要のない要素をスキップできるように、基本抽象クラスに適用するカスタム属性を持っています。基本クラスをオーバーライドするプロパティが属性を継承していないようです。

オーバーライドする基本プロパティ(抽象または仮想)は、元のプロパティに配置された属性を吹き飛ばしますか?

属性クラスの定義から

[AttributeUsage(AttributeTargets.Property,
                Inherited = true,
                AllowMultiple = false)]
public class NoHtmlOutput : Attribute
{
}

抽象クラスの定義から

[NoHtmlOutput]
public abstract Guid UniqueID { get; set; }

具体的なクラス定義から

public override Guid UniqueID{ get{ return MasterId;} set{MasterId = value;}}

クラスの属性チェックから

        Type t = o.GetType();
        foreach (PropertyInfo pi in t.GetProperties())
        {
            if (pi.GetCustomAttributes(typeof(NoHtmlOutput), true).Length == 1)
                continue;
            // processing logic goes here
        }
45
Marty Trenouth

いいえ、属性は継承されます。

親の宣言を調べないのはGetCustomAttributes()メソッドです。指定されたメンバーに適用されている属性のみを調べます。 ドキュメントから

備考

このメソッドは、プロパティとイベントの継承パラメーターを無視します。プロパティとイベントの属性の継承チェーンを検索するには、Attribute .. ::。GetCustomAttributesメソッドの適切なオーバーロードを使用します。

30
womp

次のように、PropertyInfo.GetCustomAttributes(...)を呼び出す代わりに、静的メソッドSystem.Attribute.GetCustomAttributes(pi、...)を呼び出す必要があります。

PropertyInfo info = GetType().GetProperties();

// this gets only the attributes in the derived class and ignores the 'true' parameter
object[] DerivedAttributes = info.GetCustomAttributes(typeof(MyAttribute),true);

// this gets all of the attributes up the heirarchy
object[] InheritedAttributes = System.Attribute.GetCustomAttributes(info,typeof(MyAttribute),true);
63
John Holliday

オーバーライドするメソッドにも属性がある場合にのみ発生するようです。

http://msdn.Microsoft.com/en-us/library/a19191fh.aspx

ただし、同じタイプの属性をオーバーライドしたり、派生コンポーネントに追加の属性を適用したりできます。次のコードフラグメントは、基本クラスに適用されているBrowsableAttribute属性をオーバーライドすることにより、Controlから継承されたTextプロパティをオーバーライドするカスタムコントロールを示しています。 Visual Basic

Public Class MyControl
   Inherits Control
   ' The base class has [Browsable(true)] applied to the Text property.
   <Browsable(False)>  _
   Public Overrides Property [Text]() As String
      ...
   End Property 
   ...
End Class
0
Eric Schneider

これが私の試みです。これはMemberInfoの拡張メソッドであり、継承階層を手動でウォークアップします。これは、動的プロキシと互換性があるようです...少なくとも城によって作成されたホースはとにかく、すべてのプロキシライブラリと互換性があると思います。

public static IEnumerable<T> GetCustomAttributes<T>(this MemberInfo instance)
{
    while (instance != null)
    {
        object[] attributes = instance.GetCustomAttributes(typeof(T), false);
        if (attributes.Length > 0)
        {
            return attributes.Cast<T>();
        }
        Type ancestor = instance.DeclaringType.BaseType;
        if (ancestor != null)
        {
            IEnumerable<MemberInfo> ancestormatches = ancestor.FindMembers(instance.MemberType, BindingFlags.Instance | BindingFlags.Public, 
                (m, s) =>
                {
                    return m.Name == (string)s;
                }, instance.Name);
            instance = ancestormatches.FirstOrDefault();
        }
        else
        {
            instance = null;
        }
    }
    return new T[] { };
}

そして、あなたはこのようにそれを使うでしょう。

Type t = o.GetType();
foreach (PropertyInfo pi in t.GetProperties())
{
    IEnumerable<NoHtmlOutput> attributes = pi.GetCustomAttributes<NoHtmlOutput>();
    foreach (NoHtmlOutput attribute in attributes)
    {
      Console.WriteLine(attribute);
    }
}
0
Brian Gideon

使用できます

PropertyInfo::GetCustomAttributes<T>(true)

正常に動作します。例を参照してください: https://dotnetfiddle.net/2IhEWH

したがって、静的メソッドを使用する必要はありません

System.Attribute.GetCustomAttributes
0
overt