속성에 속성이 있는지 확인


158

속성이있는 클래스의 속성이 주어지면 주어진 속성이 포함되어 있는지 확인하는 가장 빠른 방법은 무엇입니까? 예를 들면 다음과 같습니다.

    [IsNotNullable]
    [IsPK]
    [IsIdentity]
    [SequenceNameAttribute("Id")]
    public Int32 Id
    {
        get
        {
            return _Id;
        }
        set
        {
            _Id = value;
        }
    }

예를 들어 "IsIdentity"속성이 있는지 확인하는 가장 빠른 방법은 무엇입니까?

답변:


279

속성을 검색하는 빠른 방법은 없습니다. 그러나 코드는 다음과 같아야합니다 ( Aaronaught의 신용 ) :

var t = typeof(YourClass);
var pi = t.GetProperty("Id");
var hasIsIdentity = Attribute.IsDefined(pi, typeof(IsIdentity));

속성 속성을 검색해야하는 경우

var t = typeof(YourClass);
var pi = t.GetProperty("Id");
var attr = (IsIdentity[])pi.GetCustomAttributes(typeof(IsIdentity), false);
if (attr.Length > 0) {
    // Use attr[0], you'll need foreach on attr if MultiUse is true
}

63
속성이 있는지 확인하고 속성에서 정보를 검색하지 않으면 Attribute.IsDefined코드를 사용 하면 한 줄의 코드와 못생긴 배열 / 캐스팅이 제거됩니다.
Aaronaught

4
방금 이것으로 만난 것은 일부 속성의 속성 이름과 다른 유형입니다. 예를 들어, System.ComponentModel.DataAnnotations.Schema의 "NotMapped" [NotMapped]는 클래스에서와 같이 사용 되지만이를 감지하려면 다음을 사용해야합니다.Attribute.IsDefined(pi, typeof(NotMappedAttribute))
Qjimbo

2
일반 과부하를 사용하는 것이 더 쉬울 수 있습니다.IsIdentity[] attr = pi.GetCustomAttributes<IsIdentity>(false);
Mojtaba

@Qjimbo (또는 다른 사람이 읽는 사람) 속성은 일반적으로 이름의 "속성"부분없이 사용되지만 가능합니다. 규칙에 따라 제외 할 수 있으므로 일반적으로 실제 유형의 이름 끝에 속성이 있지만 사용되지는 않습니다.
짐 울프

44

.NET 3.5를 사용하는 경우 식 트리를 사용해 볼 수 있습니다. 반사보다 안전합니다.

class CustomAttribute : Attribute { }

class Program
{
    [Custom]
    public int Id { get; set; }

    static void Main()
    {
        Expression<Func<Program, int>> expression = p => p.Id;
        var memberExpression = (MemberExpression)expression.Body;
        bool hasCustomAttribute = memberExpression
            .Member
            .GetCustomAttributes(typeof(CustomAttribute), false).Length > 0;
    }
}

7
참고로 귀하의 답변에 대한 질문이 있습니다. stackoverflow.com/questions/4158996/…
그렉

12

공통 (일반) 방법을 사용하여 지정된 MemberInfo에서 속성을 읽을 수 있습니다.

public static bool TryGetAttribute<T>(MemberInfo memberInfo, out T customAttribute) where T: Attribute {
                var attributes = memberInfo.GetCustomAttributes(typeof(T), false).FirstOrDefault();
                if (attributes == null) {
                    customAttribute = null;
                    return false;
                }
                customAttribute = (T)attributes;
                return true;
            }

7

@Hans Passant의 답변을 업데이트 및 / 또는 향상시키기 위해 부동산 검색을 확장 방법으로 분리합니다. GetProperty () 메소드에서 불쾌한 마술 문자열을 제거 할 수 있다는 추가 이점이 있습니다.

public static class PropertyHelper<T>
{
    public static PropertyInfo GetProperty<TValue>(
        Expression<Func<T, TValue>> selector)
    {
        Expression body = selector;
        if (body is LambdaExpression)
        {
            body = ((LambdaExpression)body).Body;
        }
        switch (body.NodeType)
        {
            case ExpressionType.MemberAccess:
                return (PropertyInfo)((MemberExpression)body).Member;
            default:
                throw new InvalidOperationException();
        }
    }
}

그런 다음 테스트는 두 줄로 줄어 듭니다.

var property = PropertyHelper<MyClass>.GetProperty(x => x.MyProperty);
Attribute.IsDefined(property, typeof(MyPropertyAttribute));

7

휴대용 클래스 라이브러리 PCL (예 : 나와 같은) 에서이 작업을 수행하려는 경우 다음과 같이하십시오.

public class Foo
{
   public string A {get;set;}

   [Special]
   public string B {get;set;}   
}

var type = typeof(Foo);

var specialProperties = type.GetRuntimeProperties()
     .Where(pi => pi.PropertyType == typeof (string) 
      && pi.GetCustomAttributes<Special>(true).Any());

그런 다음 필요한 경우이 특수 속성이있는 속성 수를 확인할 수 있습니다.


7

이제 다음과 같은 새로운 C # 기능을 사용하여 표현식 트리와 확장 메서드없이 안전한 형식으로 수행 할 수 있습니다 nameof().

Attribute.IsDefined(typeof(YourClass).GetProperty(nameof(YourClass.Id)), typeof(IsIdentity));

nameof () 는 C # 6에서 도입되었습니다


6

Attribute.IsDefined 메소드를 사용할 수 있습니다

https://msdn.microsoft.com/en-us/library/system.attribute.isdefined(v=vs.110).aspx

if(Attribute.IsDefined(YourProperty,typeof(YourAttribute)))
{
    //Conditional execution...
}

구체적으로 찾고있는 속성을 제공하거나 다음과 같이 리플렉션을 사용하여 모든 속성을 반복 할 수 있습니다.

PropertyInfo[] props = typeof(YourClass).GetProperties();

컴파일되지 않습니다. YourProperty 또는 YourAttribute 주위에 []를 사용할 수 없습니다

모든 이전 답변은 클래스, 속성 및 속성 이름에 대한 가정을 사용했습니다.
Francis Musignac

수정 된 것 같습니다.

2

이것은 꽤 오래된 질문이지만 사용했습니다.

내 방법에는이 매개 변수가 있지만 빌드 할 수 있습니다.

Expression<Func<TModel, TValue>> expression

그런 다음이 방법에서 :

System.Linq.Expressions.MemberExpression memberExpression 
       = expression.Body as System.Linq.Expressions.MemberExpression;
Boolean hasIdentityAttr = System.Attribute
       .IsDefined(memberExpression.Member, typeof(IsIdentity));
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.