Belirli bir özniteliğe sahip özelliklerin listesi nasıl alınır?


210

Bir tür tvar ve özniteliğe sahip ortak özelliklerin bir listesini almak istiyorum MyAttribute. Özellik şu şekilde işaretlenir AllowMultiple = false:

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

Şu anda sahip olduğum şey bu, ama daha iyi bir yol olduğunu düşünüyorum:

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

Bunu nasıl geliştirebilirim? Özür dilerim, bu yineleniyorsa, bir ton yansıma ipliği var ... oldukça sıcak bir konu gibi görünüyor.


Hayır! Özelliğin bir özniteliğe sahip olup olmadığını öğrenmeden önce bir PropertyInfo'ya ihtiyacınız vardır.
Hans Passant

Yanıtlar:


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

Bu, herhangi bir öznitelik örneğini gerçekleştirmek zorunda kalmaz (yani, daha ucuzdur GetCustomAttribute[s]().


1
İyi öneri. Ancak öznitelik örneğine ihtiyacım olacak, ama hoşuma gidiyor.
wsanville

1
Ben sadece özellik denilen yan etkisi olmadan bir niteliğin varlığını kontrol etmek için bir yol arıyordu. Teşekkürler Marc, işe yarıyor!
Örjan Jämte

1
@ ÖrjanJämte özelliği getkullanılırken bile çağrılmaz GetCustomAttributes; ancak, özellik somutlaştırılmıştır , bu ücretsiz değildir. Özelliğin belirli değerlerini kontrol etmeniz gerekmiyorsa IsDefined, daha ucuzdur. Ve 4.5'te , gerçekte herhangi bir özellik örneği oluşturmadan örnekleme verilerini kontrol etmenin yolları vardır (bu yalnızca çok spesifik senaryolar için tasarlanmış olsa da )
Marc Gravell


2
dotnet çekirdeği için: var props = t.GetProperties (). Burada (e => e.IsDefined (typeof (MyAttribute)));
Rtype

45

En çok kullandığım çözüm Tomas Petricek'in cevabına dayanıyor. Genellikle hem özellik hem de özellik ile bir şeyler yapmak istiyorum .

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 - "Genellikle hem özellik hem de özellik ile bir şeyler yapmak istiyorum" aradığım şey - cevabınızı gönderdiğiniz için çok teşekkürler!
Yawar Murtaza

34

Bildiğim kadarıyla, Reflection kütüphanesi ile daha akıllıca çalışmanın daha iyi bir yolu yok. Ancak, kodu biraz daha güzel yapmak için LINQ kullanabilirsiniz:

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'

Bunun kodu daha okunabilir bir şekilde yapılandırmanıza yardımcı olduğuna inanıyorum.


13

Her zaman LINQ vardır:

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

6

Yansımalardaki Özniteliklerle düzenli olarak ilgileniyorsanız, bazı genişletme yöntemlerini tanımlamak çok, çok pratiktir. Bunu birçok projede göreceksiniz. Burada bu benim sık sık sahip olduğum bir:

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

hangi gibi kullanabilirsiniz typeof(Foo).HasAttribute<BarAttribute>();

Diğer projeler (örn. StructureMap), kimlikle ilgili iyi bir sözdizimine sahip olmak için İfade ağaçlarını kullanan tam teşekküllü ReflectionHelper sınıflarına sahiptir, örneğin PropertyInfos. Kullanım daha sonra şöyle görünür:

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

2

Önceki cevaplara ek olarak: Any()koleksiyonun uzunluğunu kontrol etmek yerine yöntemi kullanmak daha iyidir :

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

Dotnetfiddle'daki örnek: https://dotnetfiddle.net/96mKep


@ cogumel0 Her şeyden önce, .Any()uzunluğu kontrol etmeyin. Ancak cevabım, tam olarak bir niteliğe sahip bulunan mülklerle ilgili değildi. İkincisi, kodu doğru okuduğunuzdan emin değilim - .Anyyöntemin sonucu olarak adlandırılan GetCustomAttrubutesyöntem. Yani türünün propertiesWithMyAttributeözellikleri koleksiyonu olacaktır. Dotnetfiddle'daki örneğe bakın (cevaba bağlantıyı ekliyorum).
ücret

1
Herhangi bir yerde .Any ile değiştirebilirsiniz, çünkü .Any da lambdas'a izin verir.
PRMan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.