주어진 속성을 가진 속성 목록을 얻는 방법?


210

유형 t이 있으며 속성이있는 공용 속성 목록을 가져오고 싶습니다 MyAttribute. 속성은 다음과 AllowMultiple = false같이 로 표시됩니다 .

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]

현재 내가 가진 것은 이것이지만 더 나은 방법이 있다고 생각합니다.

foreach (PropertyInfo prop in t.GetProperties())
{
    object[] attributes = prop.GetCustomAttributes(typeof(MyAttribute), true);
    if (attributes.Length == 1)
    {
         //Property with my custom attribute
    }
}

이것을 어떻게 향상시킬 수 있습니까? 이것이 중복이라면 사과드립니다. 거대한 반사 스레드가 있습니다 ... 매우 인기있는 주제 인 것처럼 보입니다.


아니. 속성에 속성이 있는지 확인하려면 PropertyInfo가 필요합니다.
Hans Passant

답변:


391
var props = t.GetProperties().Where(
                prop => Attribute.IsDefined(prop, typeof(MyAttribute)));

이것은 속성 인스턴스를 구체화 할 필요가 없습니다 (즉,보다 저렴합니다 GetCustomAttribute[s]().


1
좋은 제안. 그러나 속성 인스턴스가 필요하지만 마음에 듭니다.
wsanville

1
속성이 호출되는 부작용없이 속성의 존재를 확인하는 방법을 찾고있었습니다. 고마워 마크, 작동합니다!
Örjan Jämte

1
@ ÖrjanJämte 속성 get을 사용할 때도 호출되지 않습니다 GetCustomAttributes. 그러나 속성이 인스턴스화 되어 무료가 아닙니다. 속성의 특정 값을 확인할 필요가 없으면 IsDefined저렴합니다. 4.5에서는 실제로 속성 인스턴스를 만들지 않고 인스턴스화 데이터를 확인할 수있는 방법이 있습니다 ( 매우 특정한 시나리오를 위한 것이지만 )
Marc Gravell


2
닷넷 코어의 경우 : var props = t.GetProperties (). Where (e => e.IsDefined (typeof (MyAttribute)));
Rtype

45

내가 가장 많이 사용하는 솔루션은 Tomas Petricek의 답변을 기반으로합니다. 나는 보통 뭔가하고 싶은 모두 속성과 재산을.

var props = from p in this.GetType().GetProperties()
            let attr = p.GetCustomAttributes(typeof(MyAttribute), true)
            where attr.Length == 1
            select new { Property = p, Attribute = attr.First() as MyAttribute};

+1- "보통 속성과 속성으로 무언가를하고 싶습니다"는 내가 찾던 것입니다-귀하의 답변을 게시 해 주셔서 감사합니다!
Yawar Murtaza

34

내가 아는 한, 리플렉션 라이브러리를 더 똑똑하게 작업하는 데 더 좋은 방법은 없습니다. 그러나 LINQ를 사용하여 코드를 조금 더 멋지게 만들 수 있습니다.

var props = from p in t.GetProperties()
            let attrs = p.GetCustomAttributes(typeof(MyAttribute), true)
            where attrs.Length != 0 select p;

// Do something with the properties in 'props'

이것이 코드를 더 읽기 쉬운 방식으로 구성하는 데 도움이된다고 생각합니다.


13

항상 LINQ가 있습니다 :

t.GetProperties().Where(
    p=>p.GetCustomAttributes(typeof(MyAttribute), true).Length != 0)

6

리플렉션의 속성을 정기적으로 다루는 경우 일부 확장 방법을 정의하는 것이 매우 실용적입니다. 많은 프로젝트에서 볼 수 있습니다. 여기에 제가 가진 것이 있습니다 :

public static bool HasAttribute<T>(this ICustomAttributeProvider provider) where T : Attribute
{
  var atts = provider.GetCustomAttributes(typeof(T), true);
  return atts.Length > 0;
}

당신이 사용할 수있는 typeof(Foo).HasAttribute<BarAttribute>();

다른 프로젝트 (예 : StructureMap)에는 Expression Tree를 사용하여 PropertyInfo와 같은 신원에 대한 훌륭한 구문을 갖는 본격적인 ReflectionHelper 클래스가 있습니다. 그런 다음 사용법은 다음과 같습니다.

ReflectionHelper.GetProperty<Foo>(x => x.MyProperty).HasAttribute<BarAttribute>()

2

이전 답변 외에도 Any()컬렉션 길이를 확인 하는 대신 방법을 사용하는 것이 좋습니다.

propertiesWithMyAttribute = type.GetProperties()
  .Where(x => x.GetCustomAttributes(typeof(MyAttribute), true).Any());

dotnetfiddle의 예 : https://dotnetfiddle.net/96mKep


@ cogumel0 우선, 물론 .Any() , 길이를 하지 마십시오. 그러나 내 대답은 정확히 하나의 속성을 가진 찾은 속성에 관한 것이 아닙니다. 둘째, 코드를 올바르게 읽는지 확실하지 않습니다 . 메소드 .Any의 결과에서 호출 된 GetCustomAttrubutes메소드입니다. 따라서 유형은 propertiesWithMyAttribute속성 모음입니다. dotnetfiddle에서 예제를 확인하십시오 (답변에 링크를 추가합니다).
feeeper

1
.Any는 람다도 허용하므로 .Where를 .Any로 바꿀 수 있습니다.
PRMan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.