수색…


사용자 지정 특성 만들기

//1) All attributes should be inherited from System.Attribute
//2) You can customize your attribute usage (e.g. place restrictions) by using System.AttributeUsage Attribute
//3) You can use this attribute only via reflection in the way it is supposed to be used
//4) MethodMetadataAttribute is just a name. You can use it without "Attribute" postfix - e.g. [MethodMetadata("This text could be retrieved via reflection")].
//5) You can overload an attribute constructors
[System.AttributeUsage(System.AttributeTargets.Method | System.AttributeTargets.Class)]
public class MethodMetadataAttribute : System.Attribute
{
    //this is custom field given just for an example
    //you can create attribute without any fields
    //even an empty attribute can be used - as marker
    public string Text { get; set; }

    //this constructor could be used as [MethodMetadata]
    public MethodMetadataAttribute ()
    {
    }

    //This constructor could be used as [MethodMetadata("String")]
    public MethodMetadataAttribute (string text)
    {
        Text = text;
    }
}

속성 사용

[StackDemo(Text = "Hello, World!")]
public class MyClass
{
    [StackDemo("Hello, World!")]
    static void MyMethod()
    {
    }
}

속성 읽기

메서드 GetCustomAttributes 는 멤버에 적용된 사용자 지정 특성의 배열을 반환합니다. 이 배열을 검색하면 하나 이상의 특정 속성을 검색 할 수 있습니다.

var attribute = typeof(MyClass).GetCustomAttributes().OfType<MyCustomAttribute>().Single();

또는 그들을 반복합니다.

foreach(var attribute in typeof(MyClass).GetCustomAttributes()) {
    Console.WriteLine(attribute.GetType());
}

System.Reflection.CustomAttributeExtensions GetCustomAttribute 확장 메서드는 지정된 형식의 사용자 지정 특성을 검색하며 모든 MemberInfo 적용 할 수 있습니다.

var attribute = (MyCustomAttribute) typeof(MyClass).GetCustomAttribute(typeof(MyCustomAttribute));

GetCustomAttribute 에는 검색 할 특성 유형을 지정하는 일반 서명이 있습니다.

var attribute = typeof(MyClass).GetCustomAttribute<MyCustomAttribute>();

부울 인수 inherit 은 두 메소드 모두에 전달 될 수 있습니다. 이 값을 true 설정하면 요소의 조상도 검사됩니다.

DebuggerDisplay 특성

DebuggerDisplay 속성을 추가하면 DebuggerDisplay 가 마우스를 올려 놓았을 때 클래스가 표시되는 방식이 변경됩니다.

{} 로 싸인 식은 디버거에 의해 평가됩니다. 이것은 다음 샘플 또는 더 복잡한 논리와 같은 간단한 특성 일 수 있습니다.

[DebuggerDisplay("{StringProperty} - {IntProperty}")]
public class AnObject
{
   public int ObjectId { get; set; }
   public string StringProperty { get; set; }
   public int IntProperty { get; set; }
}

디버거 표시 예제

닫는 괄호 앞에 ,nq 를 추가하면 문자열을 출력 할 때 따옴표가 제거됩니다.

[DebuggerDisplay("{StringProperty,nq} - {IntProperty}")]

{} 에 일반 표현식이 허용 되더라도 권장되지는 않습니다. DebuggerDisplay 특성은 어셈블리 메타 데이터에 문자열로 기록됩니다. {} 표현식은 유효성을 검사하지 않습니다. 그래서 좀 복잡한 논리를 포함하는 DebuggerDisplay 속성, 즉 C #에서는 제대로 작동하지만 VB.NET에서 평가 된 동일한 표현식은 구문 적으로 유효하지 않으며 디버깅하는 동안 오류가 발생합니다.

DebuggerDisplay 언어에 더 모르게 만드는 방법은 메서드 나 속성에 식을 작성하고 대신 호출하는 것입니다.

[DebuggerDisplay("{DebuggerDisplay(),nq}")]
public class AnObject
{
   public int ObjectId { get; set; }
   public string StringProperty { get; set; }
   public int IntProperty { get; set; }

   private string DebuggerDisplay()
    {
        return $"{StringProperty} - {IntProperty}"";
    }
}

DebuggerDisplay 가 모든 속성 또는 일부 속성을 출력하고 객체의 유형을 디버깅하고 검사 할 때 유용합니다.
아래 예제는 DebuggerDisplay 가 디버깅 환경에서 사용되므로 #if DEBUG 로 도우미 메서드를 둘러 쌉니다.

[DebuggerDisplay("{DebuggerDisplay(),nq}")]
public class AnObject
{
   public int ObjectId { get; set; }
   public string StringProperty { get; set; }
   public int IntProperty { get; set; }

#if DEBUG
   private string DebuggerDisplay()
    {
        return
            $"ObjectId:{this.ObjectId}, StringProperty:{this.StringProperty}, Type:{this.GetType()}";
    }
    #endif
}

발신자 정보 속성

호출자 정보 속성을 사용하여 호출자에 대한 정보를 호출 된 메소드에 전달할 수 있습니다. 선언은 다음과 같습니다.

using System.Runtime.CompilerServices;

public void LogException(Exception ex,
                         [CallerMemberName]string callerMemberName = "",
                         [CallerLineNumber]int callerLineNumber = 0,
                         [CallerFilePath]string callerFilePath = "")
{
    //perform logging
}

호출은 다음과 같이 보입니다.

public void Save(DBContext context)
{
    try
    {
        context.SaveChanges();
    }
    catch (Exception ex)
    {
        LogException(ex);
    }
}

첫 번째 매개 변수 만 LogException 메서드에 명시 적으로 전달되는 반면 나머지는 컴파일 타임에 관련 값과 함께 제공됩니다.

callerMemberName 매개 변수는 호출 메서드의 이름 인 "Save" 값을받습니다.

callerLineNumber 매개 변수는 LogException 메서드 호출이 기록 된 행 번호를받습니다.

'callerFilePath'매개 변수는 Save 메서드가 선언 된 파일의 전체 경로를받습니다.

인터페이스에서 속성 읽기

클래스는 인터페이스의 속성을 상속하지 않으므로 인터페이스에서 속성을 얻는 간단한 방법은 없습니다. 파생 클래스에서 인터페이스를 구현하거나 멤버를 재정의 할 때마다 특성을 다시 선언해야합니다. 그래서 아래의 예에서 출력은 세 가지 경우 모두 True 입니다.

using System;
using System.Linq;
using System.Reflection;

namespace InterfaceAttributesDemo {
    
    [AttributeUsage(AttributeTargets.Interface, Inherited = true)]
    class MyCustomAttribute : Attribute {
        public string Text { get; set; }
    }
    
    [MyCustomAttribute(Text = "Hello from interface attribute")]
    interface IMyClass {
        void MyMethod();
    }
    
    class MyClass : IMyClass {
        public void MyMethod() { }
    }
    
    public class Program {
        public static void Main(string[] args) {
            GetInterfaceAttributeDemo();
        }
        
        private static void GetInterfaceAttributeDemo() {
            var attribute1 = (MyCustomAttribute) typeof(MyClass).GetCustomAttribute(typeof(MyCustomAttribute), true);
            Console.WriteLine(attribute1 == null); // True
            
            var attribute2 = typeof(MyClass).GetCustomAttributes(true).OfType<MyCustomAttribute>().SingleOrDefault();
            Console.WriteLine(attribute2 == null); // True
            
            var attribute3 = typeof(MyClass).GetCustomAttribute<MyCustomAttribute>(true);
            Console.WriteLine(attribute3 == null); // True
        }
    }
}

인터페이스 속성을 검색하는 한 가지 방법은 클래스가 구현 한 모든 인터페이스를 통해 인터페이스 속성을 검색하는 것입니다.

var attribute = typeof(MyClass).GetInterfaces().SelectMany(x => x.GetCustomAttributes().OfType<MyCustomAttribute>()).SingleOrDefault();
Console.WriteLine(attribute == null); // False
Console.WriteLine(attribute.Text); // Hello from interface attribute

폐기 된 속성

System.Obsolete는 더 나은 버전을 가진 형식 또는 멤버를 표시하는 데 사용되는 특성이므로 사용해서는 안됩니다.

[Obsolete("This class is obsolete. Use SomeOtherClass instead.")]
class SomeClass
{
    //
}

위의 클래스를 사용하는 경우 컴파일러에서 "This class is obsolete. SomeOtherClass를 대신 사용하십시오."라는 경고를 표시합니다.



Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow