다음을 통해 공유


사용자 지정 특성 작성

사용자 지정 특성을 직접 디자인하는 데 새로운 개념을 모두 알 필요는 없습니다. 개체 지향 프로그래밍에 익숙하고 클래스 디자인 방법을 알고 있는 것으로 충분합니다. 사용자 지정 특성은 본래 System.Attribute에서 직접 또는 간접적으로 파생된 일반적인 클래스입니다. 일반적인 클래스와 마찬가지로 사용자 지정 특성에도 데이터를 저장하고 검색하는 메서드가 포함되어 있습니다.

사용자 지정 특성 클래스를 올바르게 디자인하는 기본 단계는 다음과 같습니다.

  • AttributeUsageAttribute 적용

  • 특성 클래스 선언

  • 생성자 선언

  • 속성 선언

이 단원에서는 각 단계에 대해 설명한 다음 마지막으로 사용자 지정 특성 예제를 보여 줍니다.

AttributeUsageAttribute 적용

사용자 지정 특성을 선언하는 과정은 AttributeUsageAttribute를 사용하여 특성 클래스의 주요 특징 일부를 정의하는 것으로 시작됩니다. 예를 들어, 다른 클래스에서 특성을 상속할 수 있는지 여부를 지정하거나 해당 특성이 적용될 수 있는 요소를 지정할 수 있습니다. 다음 코드 예제에서는 AttributeUsageAttribute의 사용 방법을 보여 줍니다.

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

System.AttributeUsageAttribute에는 사용자 지정 특성을 만드는 데 필요한 세 가지 멤버인 AttributeTargets, Inherited, 및 AllowMultiple이 포함되어 있습니다.

AttributeTargets 멤버

앞의 예제에는 특성을 모든 프로그램에 적용하는 AttributeTargets.All이 지정되어 있습니다. 또는 특성이 클래스에만 적용되도록 AttributeTargets.Class를 지정하거나 특성이 메서드에만 적용되도록 AttributeTargets.Method를 지정할 수 있습니다. 이러한 방법으로 사용자 지정 특성을 사용하여 모든 프로그램 요소의 설명을 표시할 수 있습니다.

또한 AttributeTargets의 인스턴스를 여러개 전달할 수도 있습니다. 다음 코드 예제에서는 사용자 지정 특성이 모든 클래스 또는 메서드에 적용되도록 지정합니다.

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

Inherited 속성

Inherited 속성은 특성이 적용된 클래스의 파생클래스가 해당 특성을 상속할 수 있는지 여부를 나타냅니다. 이 특성에는 true(기본값) 또는 false 플래그가 지정됩니다. 예를 들어, 다음 코드 예제에서 MyAttribute의 Inherited 값은 기본값인 true인 반면 YourAttribute의 Inherited 값은 false입니다.

' This defaults to Inherited = true.
Public Class MyAttribute
    Inherits Attribute
    '...
End Class

<AttributeUsage(AttributeTargets.Method, Inherited := False)>
Public Class YourAttribute
    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 ref class MyAttribute : Attribute
{
    //...
};

[AttributeUsage(AttributeTargets::Method, Inherited = false)]
public ref class YourAttribute : Attribute
{
    //...
};

이 두 특성은 기본 클래스인 MyClass의 메서드에 적용됩니다.

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

마지막으로, YourClass 클래스가 기본 클래스인 MyClass에서 상속됩니다. MyMethod 메서드는 MyAttribute를 표시하지만 YourAttribute는 표시하지 않습니다.

Public Class YourClass
    Inherits MeClass
    ' MyMethod will have MyAttribute but not YourAttribute.
    Public Overrides Sub MyMethod()
        '...
    End Sub

End Class
public class YourClass : MyClass
{
    // MyMethod will have MyAttribute but not YourAttribute.
    public override void MyMethod()
    {
        //...
    }

}
public ref class YourClass : MyClass
{
public:
    // MyMethod will have MyAttribute but not YourAttribute.
    virtual void MyMethod() override
    {
        //...
    }

};

AllowMultiple 속성

AllowMultiple속성은 하나의 요소에 대해 특성의 인스턴스가 여러개 있을 수 있는지 여부를 나타냅니다. 해당 속성이 true로 설정되어 있으면 여러 개의 인스턴스가 있을 수 있으며, false(기본값)로 설정되어 있으면 하나의 인스턴스만 있을 수 있습니다.

다음 코드 예제에서 MyAttribute의 AllowMultiple 값은 기본값인 false인 반면 YourAttribute의 값은 true입니다.

' This defaults to AllowMultiple = false.
Public Class MyAttribute
    Inherits Attribute
End Class

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

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class YourAttribute : Attribute
{
}
//This defaults to AllowMultiple = false.
public ref class MyAttribute : Attribute
{
};

[AttributeUsage(AttributeTargets::Method, AllowMultiple = true)]
public ref class YourAttribute : Attribute
{
};

이 특성의 인스턴스가 여러 개 적용되면 MyAttribute에서는 컴파일러 오류가 생성됩니다. 다음 코드 예제에서는 YourAttribute를 올바르게 사용한 경우와 MyAttribute를 잘못 사용한 경우를 보여 줍니다.

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
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 ref class MyClass
{
public:
    // This produces an error.
    // Duplicates are not allowed.
    [MyAttribute]
    [MyAttribute]
    void MyMethod()
    {
        //...
    }

    // This is valid.
    [YourAttribute]
    [YourAttribute]
    void YourMethod()
    {
        //...
    }
};

AllowMultiple 속성과 Inherited 속성이 모두 true로 설정된 경우에는 다른 클래스에서 상속된 클래스가 특성을 상속할 수 있으며 동일한 자식 클래스에 적용된 동일한 특성의 다른 인스턴스를 가질 수 있습니다. AllowMultiplefalse로 설정된 경우에는 자식 클래스에 있는 동일한 특성의 새 인스턴스가 부모 클래스에 있는 모든 특성 값을 덮어씁니다.

특성 클래스 선언

AttributeUsageAttribute를 적용한 다음 특성을 상세히 정의할 수 있습니다. 특성 클래스를 선언하는 과정은 다음 코드에서처럼 일반적인 클래스를 선언하는 과정과 비슷합니다.

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

이 특성 정의는 다음과 같은 몇 가지 점을 보여 줍니다.

  • 특성 클래스는 공용 클래스로 선언되어야 합니다.

  • 특성 클래스의 이름은 규칙에 따라 Attribute로 끝납니다. 이 규칙을 반드시 적용할 필요는 없지만 가독성을 향상시키기 위해 사용하는 것이 좋습니다. 특성이 적용될 때 Attribute라는 단어를 포함시키지 않을 수도 있습니다.

  • 모든 특성 클래스는 System.Attribute에서 직접 또는 간접적으로 상속해야 합니다.

  • Microsoft VisualBasic에서는 모든 사용자 지정 특성 클래스에 AttributeUsageAttribute 특성이 있습니다.

생성자 선언

특성은 일반적인 클래스와 동일한 방법으로 생성자를 사용하여 초기화됩니다. 다음 코드 예제에서는 일반적인 특성 생성자를 보여 줍니다. 이 공용 생성자는 매개 변수를 적용하여 해당 매개 변수의 값을 멤버 변수와 같은 값으로 설정합니다.

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

생성자를 오버로드하여 여러 가지 값을 조합하여 사용할 수도 있습니다. 또한 사용자 지정 특성 클래스에 대한속성을 정의하면 특성을 초기화 할때 명명된 매개변수와 위치 매개변수를 함께 사용할 수 있습니다. 일반적으로 모든 필수적 매개 변수는 positional로 정의하고 모든 선택적 매개 변수는 named로 정의합니다. 이때 필수적 매개 변수가 없으면 특성을 초기화할 수 없습니다. 다른 모든 매개 변수는 선택적 요소입니다. Visual Basic에서는 특성 클래스의 생성자가 ParamArray 인수를 사용할 수 없습니다.

다음 코드 예제에서는 앞의 생성자를 사용하는 특성이 선택적 매개 변수와 필수적 매개 변수를 사용하여 적용되는 방식을 보여 줍니다. 이 예제에서는 특성에 하나의 필수적 부울 값과 하나의 선택적 문자열 속성이 있는 것으로 가정합니다.

' 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
// 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 ref class SomeClass
{
    //...
};
// One required (positional) parameter is applied.
[MyAttribute(false)]
public ref class SomeOtherClass
{
    //...
};

속성 선언

named 매개변수를 정의하거나 특성에 의해 저장된 값을 쉽게 반환하려면 속성을 선언합니다. 특성 속성은 반환될 데이터 형식에 대한 설명이 포함된 공용 엔터티로 선언되어야 합니다. 속성 값을 포함할 변수를 정의한 다음 이를 getset 메서드와 연결합니다. 다음 코드 예제에서는 특성에 간단한 속성을 구현하는 방법을 보여 줍니다.

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

사용자 지정 특성 예제

이 단원에서는 앞에서 설명한 내용을 종합하고, 간단한 특성을 디자인하여 코드 섹션의 작성자에 대한 정보를 나타내는 방법에 대해 설명합니다. 이 예제에서 사용된 특성에는 프로그래머의 이름 및 수준과 코드 검토 여부가 저장됩니다. 이 특성은 저장할 실제 값이 포함된 세 개의 private 변수를 사용합니다. 각 변수는 값을 가져오고 설정하는 public 속성으로 표시됩니다. 마지막으로 두 개의 필수적 매개 변수를 사용하여 생성자가 정의됩니다.

<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
[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 ref class DeveloperAttribute : Attribute
{
    // Private fields.
private:
    String^ name;
    String^ level;
    bool reviewed;

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

    DeveloperAttribute(String^ name, String^ level)
    {
        this->name = name;
        this->level = level;
        this->reviewed = false;
    }

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

    virtual property String^ Name
    {
        String^ get() {return name;}
    }

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

    virtual property String^ Level
    {
        String^ get() {return level;}
    }

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

    virtual property bool Reviewed
    {
        bool get() {return reviewed;}
        void set(bool value) {reviewed = value;}
    }
};

전체 이름인 DeveloperAttribute나 약식 이름인 Developer를 다음 중 한 가지 방법으로 사용하여 이 특성을 적용할 수 있습니다.

<Developer("Joan Smith", "1")>

-or-

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

-or-

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

-or-

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

첫 번째 예제에서는 필수적 요소인 named 매개 변수만 사용하여 적용된 특성을 보여 주고, 두 번째 예제에서는 필수적 매개 변수와 선택적 매개 변수를 모두 사용하여 적용된 특성을 보여 줍니다.

참고 항목

참조

System.Attribute

AttributeUsageAttribute

개념

특성을 사용하여 메타데이터 확장