次の方法で共有


カスタム属性を記述する

カスタム属性を設計するには、多くの新しい概念を学習する必要はありません。 オブジェクト指向プログラミングに慣れているし、クラスを設計する方法を知っている場合は、既に必要な知識のほとんどがあります。 カスタム属性は、 クラスから直接または間接的に派生する従来のクラスです。 従来のクラスと同様に、カスタム属性にはデータを格納および取得するメソッドが含まれています。

カスタム属性クラスを適切に設計する主な手順は次のとおりです。

  • AttributeUsageAttribute の適用

  • 属性クラスの宣言

  • コンストラクターの宣言

  • プロパティの宣言

このセクションでは、これらの各手順について説明し、最後に カスタム属性の例を示します。

AttributeUsageAttribute の適用

カスタム属性宣言は、属性クラスの主要な特性の一部を定義する 属性で始まります。 たとえば、属性を他のクラスで継承できるかどうか、または属性を適用できる要素を指定できます。 次のコード フラグメントは、 の使用方法を示しています。

[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)]
<AttributeUsage(AttributeTargets.All, Inherited:=False, AllowMultiple:=True)>
Public Class SomeClass
    Inherits Attribute
    '...
End Class

には、カスタム属性の作成に重要な 3 つのメンバー (AttributeTargets、Inherited、AllowMultiple) があります。

AttributeTargets メンバー

前の例では、 を指定し、この属性をすべてのプログラム要素に適用できることを示しています。 または、 を指定して、属性をクラスにのみ適用できることを示すか、 、属性をメソッドにのみ適用できることを示します。 すべてのプログラム要素は、この方法でカスタム属性によって説明用にマークできます。

複数の 値を渡すこともできます。 次のコード フラグメントは、カスタム属性を任意のクラスまたはメソッドに適用できることを指定します。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
<AttributeUsage(AttributeTargets.Class Or AttributeTargets.Method)>
Public Class SomeOtherClass
    Inherits Attribute
    '...
End Class

継承されたプロパティ

プロパティは、属性が適用されるクラスから派生したクラスによって属性を継承できるかどうかを示します。 このプロパティは、 (既定値) または フラグを受け取ります。 次の例では、 の既定の 値は ですが、 の 値は です。

// This defaults to Inherited = true.
public class MyAttribute : Attribute
{
    //...
}

[AttributeUsage(AttributeTargets.Method, Inherited = false)]
public class YourAttribute : Attribute
{
    //...
}
' This defaults to Inherited = true.
Public Class MyAttribute
    Inherits Attribute
    '...
End Class

<AttributeUsage(AttributeTargets.Method, Inherited:=False)>
Public Class YourAttribute
    Inherits Attribute
    '...
End Class

次に、基底クラスのメソッドに次の 2 つの属性が適用 。

public class MyClass
{
    [MyAttribute]
    [YourAttribute]
    public virtual void MyMethod()
    {
        //...
    }
}
Public Class MeClass
    <MyAttribute>
    <YourAttribute>
    Public Overridable Sub MyMethod()
        '...
    End Sub
End Class

最後に、 クラスは基底クラスの から継承されます。 メソッドが表示されますが、は表示されません。

public class YourClass : MyClass
{
    // MyMethod will have MyAttribute but not YourAttribute.
    public override void MyMethod()
    {
        //...
    }
}
Public Class YourClass
    Inherits MeClass
    ' MyMethod will have MyAttribute but not YourAttribute.
    Public Overrides Sub MyMethod()
        '...
    End Sub

End Class

AllowMultiple プロパティ

プロパティは、属性の複数のインスタンスが要素に存在できるかどうかを示します。 に設定すると、複数のインスタンスが許可されます。 (既定値) に設定すると、1 つのインスタンスのみが許可されます。

次の例では、 の既定の 値は ですが、 の値は です。

//This defaults to AllowMultiple = false.
public class MyAttribute : Attribute
{
}

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class YourAttribute : Attribute
{
}
' This defaults to AllowMultiple = false.
Public Class MyAttribute
    Inherits Attribute
End Class

<AttributeUsage(AttributeTargets.Method, AllowMultiple:=true)>
Public Class YourAttribute
    Inherits Attribute
End Class

これらの属性の複数のインスタンスが適用されると、 コンパイラ エラーが発生します。 次のコード例は、 の有効な使用方法と、 の無効な使用を示しています。

public class MyClass
{
    // This produces an error.
    // Duplicates are not allowed.
    [MyAttribute]
    [MyAttribute]
    public void MyMethod()
    {
        //...
    }

    // This is valid.
    [YourAttribute]
    [YourAttribute]
    public void YourMethod()
    {
        //...
    }
}
Public Class MyClass
    ' This produces an error.
    ' Duplicates are not allowed.
    <MyAttribute>
    <MyAttribute>
    Public Sub MyMethod()
        '...
    End Sub

    ' This is valid.
    <YourAttribute>
    <YourAttribute>
    Public Sub YourMethod()
        '...
    End Sub
End Class

プロパティと プロパティの両方が に設定されている場合、別のクラスから継承されたクラスは属性を継承し、同じ子クラスに同じ属性の別のインスタンスを適用できます。 が に設定されている場合、親クラス内の属性の値は、子クラス内の同じ属性の新しいインスタンスによって上書きされます。

属性クラスの宣言

を適用したら、属性の詳細の定義を開始します。 属性クラスの宣言は、次のコードで示すように、従来のクラスの宣言に似ています。

[AttributeUsage(AttributeTargets.Method)]
public class MyAttribute : Attribute
{
    // . . .
}
<AttributeUsage(AttributeTargets.Method)>
Public Class MyAttribute
    Inherits Attribute
    ' . . .
End Class

この属性定義は、次の点を示しています。

  • 属性クラスはパブリック クラスとして宣言する必要があります。

  • 慣例により、属性クラスの名前は Attribute という単語で終わります。 この規則は必須ではありませんが、読みやすくするために推奨されます。 属性を適用する場合、属性という単語を含めることは省略可能です。

  • すべての属性クラスは、 クラスから直接または間接的に継承する必要があります。

  • Microsoft Visual Basic では、すべてのカスタム属性クラスに System.AttributeUsageAttribute 属性が必要です。

コンストラクターの宣言

従来のクラスと同様に、属性はコンストラクターで初期化されます。 次のコード フラグメントは、一般的な属性コンストラクターを示しています。 このパブリック コンストラクターはパラメーターを受け取り、その値と等しいメンバー変数を設定します。

public MyAttribute(bool myvalue)
{
    this.myvalue = myvalue;
}
Public Sub New(myvalue As Boolean)
    Me.myvalue = myvalue
End Sub

コンストラクターをオーバーロードして、さまざまな値の組み合わせに対応できます。 カスタム属性クラスの プロパティ も定義する場合は、属性の初期化時に名前付きパラメーターと位置指定パラメーターの組み合わせを使用できます。 通常、必要なすべてのパラメーターを位置指定パラメーターとして定義し、すべての省略可能なパラメーターを名前付きとして定義します。 この場合、必要なパラメーターがないと属性を初期化できません。 その他のパラメーターはすべて省略可能です。

Visual Basicでは、属性クラスのコンストラクターでは、ParamArray 引数を使用しないでください。

ランタイムはメタデータから属性値を直接読み取ることができる必要があるため、属性のコンストラクター パラメーターとパブリック プロパティは限られた型のセットに制限されます。 有効な属性パラメーターの型は次のとおりです。

  • 単純型 (C# キーワード/Visual Basic キーワード/.NETランタイム型):

    C# Visual Basic .NETランタイムの種類
    bool Boolean Boolean
    byte Byte Byte
    char Char Char
    double Double Double
    float Single Single
    int Integer Int32
    long Long Int64
    short Short Int16
    string String String
  • 属性の使用箇所でアクセス可能な列挙型。

  • C# で します (値が有効な属性引数の型のいずれか、またはその 1 次元配列である場合)。

  • 上記のいずれかの型の 1 次元配列。

このリストの外部にある型を受け入れるコンストラクターを定義すると、属性は正常にコンパイルされますが、適用しようとするとコンパイラ エラーが発生します。 属性の適用時に許可される式の詳細については、「 属性の適用」を参照してください。

リテラル定数をサポートしていても、 、 、 、 、 、 、および の型は有効な属性パラメーター型ではありません。

次のコード例は、省略可能なパラメーターと必須パラメーターを使用して、前のコンストラクターを使用する属性を適用する方法を示しています。 この属性には、1 つの必須のブール値と 1 つの省略可能な文字列プロパティがあることを前提としています。

// One required (positional) and one optional (named) parameter are applied.
[MyAttribute(false, OptionalParameter = "optional data")]
public class SomeClass
{
    //...
}
// One required (positional) parameter is applied.
[MyAttribute(false)]
public class SomeOtherClass
{
    //...
}
' One required (positional) and one optional (named) parameter are applied.
<MyAttribute(false, OptionalParameter:="optional data")>
Public Class SomeClass
    '...
End Class

' One required (positional) parameter is applied.
<MyAttribute(false)>
Public Class SomeOtherClass
    '...
End Class

プロパティの宣言

名前付きパラメーターを定義する場合、または属性によって格納されている値を簡単に返す方法を提供する場合は、プロパティを宣言 します。 属性プロパティは、返されるデータ型の説明を持つパブリック エンティティとして宣言する必要があります。 プロパティの値を保持する変数を定義し、 メソッドおよび メソッドに関連付けます。 次のコード例は、属性にプロパティを実装する方法を示しています。

public bool MyProperty
{
    get {return this.myvalue;}
    set {this.myvalue = value;}
}
Public Property MyProperty As Boolean
    Get
        Return Me.myvalue
    End Get
    Set
        Me.myvalue = Value
    End Set
End Property

カスタム属性の例

このセクションでは、前の情報を組み込み、コードセクションの作成者に関する情報を文書化する属性を設計する方法を示します。 この例の属性は、プログラマの名前とレベル、およびコードがレビューされたかどうかを格納します。 3 つのプライベート変数を使用して、保存する実際の値を格納します。 各変数は、値を取得および設定するパブリック プロパティによって表されます。 最後に、コンストラクターは 2 つの必須パラメーターで定義されます。

[AttributeUsage(AttributeTargets.All)]
public class DeveloperAttribute : Attribute
{
    // Private fields.
    private string name;
    private string level;
    private bool reviewed;

    // This constructor defines two required parameters: name and level.

    public DeveloperAttribute(string name, string level)
    {
        this.name = name;
        this.level = level;
        this.reviewed = false;
    }

    // Define Name property.
    // This is a read-only attribute.

    public virtual string Name
    {
        get {return name;}
    }

    // Define Level property.
    // This is a read-only attribute.

    public virtual string Level
    {
        get {return level;}
    }

    // Define Reviewed property.
    // This is a read/write attribute.

    public virtual bool Reviewed
    {
        get {return reviewed;}
        set {reviewed = value;}
    }
}
<AttributeUsage(AttributeTargets.All)>
Public Class DeveloperAttribute
    Inherits Attribute
    ' Private fields.
    Private myname As String
    Private mylevel As String
    Private myreviewed As Boolean

    ' This constructor defines two required parameters: name and level.

    Public Sub New(name As String, level As String)
        Me.myname = name
        Me.mylevel = level
        Me.myreviewed = False
    End Sub

    ' Define Name property.
    ' This is a read-only attribute.

    Public Overridable ReadOnly Property Name() As String
        Get
            Return myname
        End Get
    End Property

    ' Define Level property.
    ' This is a read-only attribute.

    Public Overridable ReadOnly Property Level() As String
        Get
            Return mylevel
        End Get
    End Property

    ' Define Reviewed property.
    ' This is a read/write attribute.

    Public Overridable Property Reviewed() As Boolean
        Get
            Return myreviewed
        End Get
        Set
            myreviewed = value
        End Set
    End Property
End Class

この属性は、フル ネーム、 、または省略名の を使用して、次のいずれかの方法で適用できます。

[Developer("Joan Smith", "1")]

-or-

[Developer("Joan Smith", "1", Reviewed = true)]
<Developer("Joan Smith", "1")>

-or-

<Developer("Joan Smith", "1", Reviewed := true)>

最初の例では、必須の名前付きパラメーターのみを使用して適用される属性を示します。 2 番目の例は、必須パラメーターと省略可能なパラメーターの両方で適用される属性を示しています。

こちらも参照ください