1010using System . Linq ;
1111using System . Reflection ;
1212using Xtensive . Core ;
13- using AttributesKey = System . ValueTuple < System . Reflection . MemberInfo , System . Type , Xtensive . Reflection . AttributeSearchOptions > ;
1413using PerAttributeKey = System . ValueTuple < System . Reflection . MemberInfo , Xtensive . Reflection . AttributeSearchOptions > ;
1514
1615namespace Xtensive . Reflection
@@ -20,22 +19,65 @@ namespace Xtensive.Reflection
2019 /// </summary>
2120 public static class AttributeHelper
2221 {
23- internal class AttributeExtractors < TAttribute > where TAttribute : Attribute
24- {
25- internal static readonly Func < PerAttributeKey , TAttribute [ ] > AttributesExtractor = key => {
26- var uncasted = GetAttributes ( key . Item1 , typeof ( TAttribute ) , key . Item2 ) ;
27- return uncasted . Count > 0
28- ? uncasted . Cast < TAttribute > ( ) . ToArray ( uncasted . Count )
29- : Array . Empty < TAttribute > ( ) ;
30- } ;
31- }
32-
3322 private static class AttributeDictionary < TAttribute > where TAttribute : Attribute
3423 {
24+ private static readonly Type attributeType = typeof ( TAttribute ) ;
3525 public static readonly ConcurrentDictionary < PerAttributeKey , TAttribute [ ] > Dictionary = new ( ) ;
36- }
3726
38- private static readonly ConcurrentDictionary < AttributesKey , IReadOnlyList < Attribute > > AttributesByMemberInfoAndSearchOptions = new ( ) ;
27+ public static readonly Func < PerAttributeKey , TAttribute [ ] > AttributesExtractor = ExtractAttributesByKey ;
28+
29+ private static TAttribute [ ] ExtractAttributesByKey ( PerAttributeKey key )
30+ {
31+ var ( member , options ) = key ;
32+
33+ var attributesAsObjects = member . GetCustomAttributes ( attributeType , false ) ;
34+ var attributesCount = attributesAsObjects . Length ;
35+
36+ var attributes = attributesCount > 0
37+ ? attributesAsObjects . Cast < TAttribute > ( ) . ToList ( attributesCount )
38+ : null ;
39+
40+ if ( options != AttributeSearchOptions . InheritNone ) {
41+ if ( attributesCount == 0 ) {
42+ if ( ( options & AttributeSearchOptions . InheritFromPropertyOrEvent ) != 0
43+ && member is MethodInfo m
44+ && ( ( MemberInfo ) m . GetProperty ( ) ?? m . GetEvent ( ) ) is MemberInfo poe ) {
45+ attributes = GetAttributesAsNewList ( poe ) ;
46+ }
47+ if ( ( options & AttributeSearchOptions . InheritFromBase ) != 0
48+ && ( options & AttributeSearchOptions . InheritFromAllBase ) == 0 ) {
49+ AddAttributesFromBase ( ref attributes , member , options ) ;
50+ }
51+ }
52+
53+ if ( ( options & AttributeSearchOptions . InheritFromAllBase ) != 0
54+ && member . DeclaringType != WellKnownTypes . Object ) {
55+ AddAttributesFromBase ( ref attributes , member , options ) ;
56+ }
57+ }
58+
59+ return attributes ? . ToArray ( attributes . Count ) ?? Array . Empty < TAttribute > ( ) ;
60+ }
61+
62+ private static List < TAttribute > GetAttributesAsNewList ( MemberInfo member )
63+ {
64+ var attrObjects = member . GetCustomAttributes ( attributeType , false ) ;
65+ var attrs = new List < TAttribute > ( attrObjects . Length ) ;
66+ for ( int i = 0 , count = attrObjects . Length ; i < count ; ++ i ) {
67+ attrs . Add ( ( TAttribute ) attrObjects [ i ] ) ;
68+ }
69+ return attrs ;
70+ }
71+
72+ private static void AddAttributesFromBase ( ref List < TAttribute > attributes , MemberInfo member , AttributeSearchOptions options )
73+ {
74+ if ( member . GetBaseMember ( ) is MemberInfo bm ) {
75+ var attrsToAdd = bm . GetAttributes < TAttribute > ( options ) ;
76+ if ( attrsToAdd . Count > 0 ) {
77+ ( attributes ??= new List < TAttribute > ( attrsToAdd . Count ) ) . AddRange ( attrsToAdd ) ;
78+ }
79+ }
80+ }
3981
4082 /// <summary>
4183 /// A shortcut to <see cref="MemberInfo.GetCustomAttributes(Type,bool)"/> method.
@@ -47,7 +89,7 @@ private static class AttributeDictionary<TAttribute> where TAttribute : Attribut
4789 ///
4890 public static IReadOnlyList < TAttribute > GetAttributes < TAttribute > ( this MemberInfo member , AttributeSearchOptions options = AttributeSearchOptions . InheritNone )
4991 where TAttribute : Attribute =>
50- AttributeDictionary < TAttribute > . Dictionary . GetOrAdd ( new PerAttributeKey ( member , options ) , AttributeExtractors < TAttribute > . AttributesExtractor ) ;
92+ AttributeDictionary < TAttribute > . Dictionary . GetOrAdd ( new PerAttributeKey ( member , options ) , AttributeDictionary < TAttribute > . AttributesExtractor ) ;
5193
5294 /// <summary>
5395 /// A version of <see cref="GetAttributes{TAttribute}(MemberInfo, AttributeSearchOptions)"/>
@@ -73,62 +115,5 @@ public static TAttribute GetAttribute<TAttribute>(this MemberInfo member, Attrib
73115 typeof ( TAttribute ) . GetShortName ( ) ) )
74116 } ;
75117 }
76-
77- private static IReadOnlyList < Attribute > GetAttributes ( MemberInfo member , Type attributeType , AttributeSearchOptions options ) =>
78- AttributesByMemberInfoAndSearchOptions . GetOrAdd (
79- new AttributesKey ( member , attributeType , options ) ,
80- ExtractAttributes
81- ) ;
82-
83- private static List < Attribute > GetAttributesAsNewList ( this MemberInfo member , Type attributeType )
84- {
85- var attrObjects = member . GetCustomAttributes ( attributeType , false ) ;
86- var attrs = new List < Attribute > ( attrObjects . Length ) ;
87- for ( int i = 0 , count = attrObjects . Length ; i < count ; ++ i ) {
88- attrs . Add ( ( Attribute ) attrObjects [ i ] ) ;
89- }
90- return attrs ;
91- }
92-
93- private static IReadOnlyList < Attribute > ExtractAttributes ( ( MemberInfo member , Type attributeType , AttributeSearchOptions options ) t )
94- {
95- ( var member , var attributeType , var options ) = t ;
96-
97- var attributesAsObjects = member . GetCustomAttributes ( attributeType , false ) ;
98- var attributesCount = attributesAsObjects . Length ;
99-
100- var attributes = attributesCount > 0
101- ? attributesAsObjects . Cast < Attribute > ( ) . ToList ( attributesCount )
102- : null ;
103-
104- if ( options != AttributeSearchOptions . InheritNone ) {
105- if ( attributesCount == 0 ) {
106- if ( ( options & AttributeSearchOptions . InheritFromPropertyOrEvent ) != 0
107- && member is MethodInfo m
108- && ( ( MemberInfo ) m . GetProperty ( ) ?? m . GetEvent ( ) ) is MemberInfo poe ) {
109- attributes = poe . GetAttributesAsNewList ( attributeType ) ;
110- }
111- if ( ( options & AttributeSearchOptions . InheritFromBase ) != 0
112- && ( options & AttributeSearchOptions . InheritFromAllBase ) == 0
113- && member . GetBaseMember ( ) is MemberInfo bm ) {
114- var attrsToAdd = GetAttributes ( bm , attributeType , options ) ;
115- if ( attrsToAdd . Count > 0 ) {
116- ( attributes ??= new List < Attribute > ( attrsToAdd . Count ) ) . AddRange ( attrsToAdd ) ;
117- }
118- }
119- }
120-
121- if ( ( options & AttributeSearchOptions . InheritFromAllBase ) != 0
122- && member . DeclaringType != WellKnownTypes . Object
123- && member . GetBaseMember ( ) is MemberInfo bm2 ) {
124- var attrsToAdd = GetAttributes ( bm2 , attributeType , options ) ;
125- if ( attrsToAdd . Count > 0 ) {
126- ( attributes ??= new List < Attribute > ( attrsToAdd . Count ) ) . AddRange ( attrsToAdd ) ;
127- }
128- }
129- }
130-
131- return ( IReadOnlyList < Attribute > ) attributes ?? Array . Empty < Attribute > ( ) ;
132- }
133118 }
134119}
0 commit comments