Jak uzyskać listę właściwości z danym atrybutem?
Mam typ t
i chciałbym uzyskać listę publicznych właściwości, które mają atrybut MyAttribute
. Atrybut jest oznaczony AllowMultiple = false
, tak:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
Obecnie mam to, ale myślę, że jest lepszy sposób:
foreach (PropertyInfo prop in t.GetProperties())
{
object[] attributes = prop.GetCustomAttributes(typeof(MyAttribute), true);
if (attributes.Length == 1)
{
//Property with my custom attribute
}
}
Jak mogę to poprawić? Przepraszam, jeśli to duplikat, jest tam mnóstwo wątków refleksji...wygląda na to, że to gorący temat.
7 answers
var props = t.GetProperties().Where(
prop => Attribute.IsDefined(prop, typeof(MyAttribute)));
Pozwala to uniknąć zmaterializowania jakichkolwiek instancji atrybutów (tzn. jest to tańsze niż GetCustomAttribute[s]()
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-17 16:09:52
Rozwiązanie, z którego najczęściej korzystam, opiera się na odpowiedzi Tomasa Petricka. Zazwyczaj chcę zrobić coś z ZARÓWNO atrybutem jak i właściwością.
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};
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-09 17:38:52
Z tego, co wiem, nie ma lepszego sposobu na mądrzejszą pracę z biblioteką Reflection. Możesz jednak użyć LINQ, aby uczynić kod nieco ładniejszym:
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'
Wierzę, że to pomaga uporządkować kod w bardziej czytelny sposób.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-18 21:35:57
Zawsze jest LINQ:
t.GetProperties().Where(
p=>p.GetCustomAttributes(typeof(MyAttribute), true).Length != 0)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-17 15:43:10
Jeśli masz do czynienia regularnie z atrybutami W Reflection, bardzo praktyczne jest zdefiniowanie niektórych metod rozszerzenia. Zobaczysz to w wielu projektach. Ten tutaj jest taki, który często mam:
public static bool HasAttribute<T>(this ICustomAttributeProvider provider) where T : Attribute
{
var atts = provider.GetCustomAttributes(typeof(T), true);
return atts.Length > 0;
}
Które możesz użyć jak typeof(Foo).HasAttribute<BarAttribute>();
Inne projekty (np. StructureMap) mają pełnowartościowe klasy ReflectionHelper, które używają drzew wyrażeń, aby mieć dokładną składnię do tożsamości, np. PropertyInfos. Użycie wtedy wygląda tak:
ReflectionHelper.GetProperty<Foo>(x => x.MyProperty).HasAttribute<BarAttribute>()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-17 16:00:56
Oprócz poprzednich odpowiedzi: lepiej użyć metody Any()
zamiast sprawdzić długość zbioru:
propertiesWithMyAttribute = type.GetProperties()
.Where(x => x.GetCustomAttributes(typeof(MyAttribute), true).Any());
Przykład dotnetfiddle: https://dotnetfiddle.net/96mKep
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-05 09:58:21
The better way:
//if (attributes.Length == 1)
if (attributes.Length != 0)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-24 14:22:24