[C#] AttributeUsageAttribute

Date:     Updated:

카테고리:

태그:

AttributeUsageAttribute에 대해 사용 및 테스트하고 작성한 글이다.

AttributeUsageAttribute

  • Attribute에 옵션을 부여할 수 있는 Attribute이다
    • ValidOn : Attribute를 사용할 수 있는 대상을 지정
    • AllowMultiple : 하나의 요소에 2번 이상의 Attribute를 지정할 수 있는지 여부
    • Inherited : 파생 클래스나 재정의 멤버에게도 Attribute상속되는지 여부

ValidOn

  • AttributeTarges을 사용해 해당 Attribute를 지정할 수 있는 대상을 제한할 수 있다
    • ex) Class, Field, Property, …
  • 원치 않는 요소가 해당 Attribute를 지정할 수 있는 경우를 미리 방지할 수 있다
[AttributeUsage(AttributeTargets.Class)]
public class ClassAttribute : Attribute
{
}

// 아래의 경우 컴파일 에러 발생
[ClassAttribute]
public struct TestStruct
{
}

AllowMultiple

  • 하나의 요소가 해당 Attribute2번 이상 지정할 수 있는지 여부
    • 쉽게 말하면 하나의 요소에 해당 Attribute 정보가 여러개 존재할 수 있는가 이다
  • 결과 (베이스와 파생 클래스 둘 다 같은 Attribute를 지정한 경우)
    • true인 경우 파생 클래스에는 베이스 클래스의 Attribute 정보도 남아 있다
    • false인 경우 파생 클래스에는 파생 클래스의 Attribute 정보만 남아 있다 (override)
public class Program
{
    static void Main(string[] args)
    {
        ShowCustomAttributes<DerivedClass, AllowMultipleAttribute>();
        // 결과
        // [AllowMultipleAttribute] DerivedClass
        // [AllowMultipleAttribute] BaseClass_1
        // [AllowMultipleAttribute] BaseClass_2


        ShowCustomAttributes<DerivedClass, DenyMultipleAttribute>();
        // 결과
        // [DenyMultipleAttribute] DerivedClass
    }

    private static void ShowCustomAttributes<TClass, TAttribute>(bool inherit = true)
        where TClass : AttributeClass
        where TAttribute : BaseAttribute
    {
        foreach (var attribute in typeof(TClass).GetCustomAttributes<TAttribute>(inherit))
            attribute.ShowAttributeInfo();
    }
}


public abstract class BaseAttribute : Attribute
{
    public virtual void ShowAttributeInfo() { }
}

[AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
public class AllowMultipleAttribute : BaseAttribute
{
    public string Name { get; set; }

    public override void ShowAttributeInfo()
    {
        Console.WriteLine($"[AllowMultipleAttribute] {Name}");
    }
}

[AttributeUsage(AttributeTargets.All, AllowMultiple = false)]
public class DenyMultipleAttribute : BaseAttribute
{
    public string Name { get; set; }

    public override void ShowAttributeInfo()
    {
        Console.WriteLine($"[DenyMultipleAttribute] {Name}");
    }
}


public abstract class AttributeClass { }

[AllowMultipleAttribute(Name = "BaseClass_1")]
[AllowMultipleAttribute(Name = "BaseClass_2")]
[DenyMultipleAttribute(Name = "BaseClass")]
public class BaseClass : AttributeClass { }

[AllowMultipleAttribute(Name = "DerivedClass")]
[DenyMultipleAttribute(Name = "DerivedClass")]
public class DerivedClass : BaseClass { }

Inherited

  • 파생 클래스나 재정의 멤버에게도 Attribute가 상속되는지 여부
  • 결과
    • true인 경우 파생 클래스에서 부모에 지정된 Attribute를 상속 받는다
    • false인 경우 파생 클래스에서 부모에 지정된 Attribute를 상속 받지 못 한다
public class Program
{
    static void Main(string[] args)
    {
        ShowCustomAttributes<DerivedClass, InheritedTrueAttribute>();
        // 결과
        // [InheritedTrueAttribute] BaseClass


        ShowCustomAttributes<DerivedClass, InheritedFalseAttribute>();
        // 결과
        // 
    }

    private static void ShowCustomAttributes<TClass, TAttribute>(bool inherit = true)
        where TClass : AttributeClass
        where TAttribute : BaseAttribute
    {
        foreach (var attribute in typeof(TClass).GetCustomAttributes<TAttribute>(inherit))
            attribute.ShowAttributeInfo();
    }
}


public abstract class BaseAttribute : Attribute
{
    public virtual void ShowAttributeInfo() { }
}

[AttributeUsage(AttributeTargets.All, Inherited = true)]
public class InheritedTrueAttribute : BaseAttribute
{
    public string Name { get; set; }

    public override void ShowAttributeInfo()
    {
        Console.WriteLine($"[InheritedTrueAttribute] {Name}");
    }
}

[AttributeUsage(AttributeTargets.All, Inherited = false)]
public class InheritedFalseAttribute : BaseAttribute
{
    public string Name { get; set; }

    public override void ShowAttributeInfo()
    {
        Console.WriteLine($"[InheritedFalseAttribute] {Name}");
    }
}


public abstract class AttributeClass { }

[InheritedTrueAttribute(Name = "BaseClass")]
[InheritedFalseAttribute(Name = "BaseClass")]
public class BaseClass : AttributeClass { }

public class DerivedClass : BaseClass { }

단순한 호기심

  • 만약 BaseAttributeAttributeUsageAttribute를 지정한 후 DerivedAttribute에 상속한 경우 AttributeUsageAttributeDerivedAttribute에 상속될까?
    • 테스트 결과 DericedAttribute에서 AttributeUsageAttribute를 다시 지정하지 않는 이상 Inherited 여부 상관없이 부모의 AttributeUsageAttribute를 상속 받는다
    • 다만 ValidOnAllowMultiple만 상속되며 Inherited는 상속되지 못 한다
[AttributeUsage(AttributeTargets.Struct, AllowMultiple = true, Inherited = false)]
public abstract class BaseAttribute : Attribute { }

public class DerivedAttribute : BaseAttribute { }


// AllowMultiple은 상속되었기 때문에 중복 지정에 대한 Error는 발생하지 않는다
[DerivedAttribute]   // Error : struct에 사용할 수 없는 Attribute 
[DerivedAttribute]   // Error : struct에 사용할 수 없는 Attribute
public class TestClass { }

참조

관련 코드



💻 열심히 공부해서 작성 중이니 오류나 틀린 부분이 있을 경우 
  언제든지 댓글 혹은 메일로 알려주시면 감사하겠습니다! 😸

맨 위로 이동하기

CSharp 카테고리 내 다른 글 보러가기

댓글 남기기