@@ -23,8 +23,7 @@ public static class AttributeHelper
2323 {
2424 internal class AttributeExtractors < TAttribute > where TAttribute : Attribute
2525 {
26- internal static readonly Func < PerAttributeKey , TAttribute [ ] > AttributesExtractor = key =>
27- {
26+ internal static readonly Func < PerAttributeKey , TAttribute [ ] > AttributesExtractor = key => {
2827 var uncasted = GetAttributes ( key . Item1 , typeof ( TAttribute ) , key . Item2 ) ;
2928 return uncasted . Count > 0
3029 ? uncasted . Cast < TAttribute > ( ) . ToArray ( uncasted . Count )
@@ -77,65 +76,60 @@ public static TAttribute GetAttribute<TAttribute>(this MemberInfo member, Attrib
7776 }
7877
7978 private static IReadOnlyList < Attribute > GetAttributes ( MemberInfo member , Type attributeType , AttributeSearchOptions options ) =>
80- AttributesByMemberInfoAndSearchOptions . GetOrAdd (
81- new AttributesKey ( member , attributeType , options ) ,
82- t => ExtractAttributes ( t , out var count ) . ToArray ( count )
83- ) ;
79+ AttributesByMemberInfoAndSearchOptions . GetOrAdd (
80+ new AttributesKey ( member , attributeType , options ) ,
81+ ExtractAttributes
82+ ) ;
8483
85- private static IEnumerable < Attribute > GetAttributes ( this MemberInfo member , Type attributeType , out int count )
84+ private static List < Attribute > GetAttributesAsNewList ( this MemberInfo member , Type attributeType )
8685 {
8786 var attrObjects = member . GetCustomAttributes ( attributeType , false ) ;
88- count = attrObjects . Length ;
89- return ( count == 0 )
90- ? Array . Empty < Attribute > ( )
91- : attrObjects . Cast < Attribute > ( ) ;
87+ var attrs = new List < Attribute > ( attrObjects . Length ) ;
88+ for ( int i = 0 , count = attrObjects . Length ; i < count ; ++ i ) {
89+ attrs . Add ( ( Attribute ) attrObjects [ i ] ) ;
90+ }
91+ return attrs ;
9292 }
9393
94- private static IEnumerable < Attribute > ExtractAttributes ( ( MemberInfo member , Type attributeType , AttributeSearchOptions options ) t , out int count )
94+ private static IReadOnlyList < Attribute > ExtractAttributes ( ( MemberInfo member , Type attributeType , AttributeSearchOptions options ) t )
9595 {
9696 ( var member , var attributeType , var options ) = t ;
9797
98- var customAttributesRaw = member . GetCustomAttributes ( attributeType , false ) ;
99- count = customAttributesRaw . Length ;
98+ var attributesAsObjects = member . GetCustomAttributes ( attributeType , false ) ;
99+ var attributesCount = attributesAsObjects . Length ;
100100
101- if ( options == AttributeSearchOptions . InheritNone ) {
102- return ( customAttributesRaw . Length == 0 )
103- ? Array . Empty < Attribute > ( )
104- : customAttributesRaw . Cast < Attribute > ( ) ;
105- }
101+ var attributes = attributesCount > 0
102+ ? attributesAsObjects . Cast < Attribute > ( ) . ToList ( attributesCount )
103+ : null ;
106104
107- IEnumerable < Attribute > attributes ;
108- if ( customAttributesRaw . Length == 0 ) {
109- attributes = Enumerable . Empty < Attribute > ( ) ;
110- if ( ( options & AttributeSearchOptions . InheritFromPropertyOrEvent ) != 0
111- && member is MethodInfo m
112- && ( ( MemberInfo ) m . GetProperty ( ) ?? m . GetEvent ( ) ) is MemberInfo poe ) {
113- var poeAttributes = poe . GetAttributes ( attributeType , out var count1 ) ;
114- count = count1 ;
115- attributes = poeAttributes ;
116- }
117- if ( ( options & AttributeSearchOptions . InheritFromBase ) != 0
118- && ( options & AttributeSearchOptions . InheritRecursively ) == 0
119- && member . GetBaseMember ( ) is MemberInfo bm ) {
120- var inheritedAttributes = GetAttributes ( bm , attributeType , options ) ;
121- count += inheritedAttributes . Count ;
122- attributes = attributes . Concat ( inheritedAttributes ) ;
123- return attributes ;
105+ if ( options != AttributeSearchOptions . InheritNone ) {
106+ if ( attributesCount == 0 ) {
107+ if ( ( options & AttributeSearchOptions . InheritFromPropertyOrEvent ) != 0
108+ && member is MethodInfo m
109+ && ( ( MemberInfo ) m . GetProperty ( ) ?? m . GetEvent ( ) ) is MemberInfo poe ) {
110+ attributes = poe . GetAttributesAsNewList ( attributeType ) ;
111+ }
112+ if ( ( options & AttributeSearchOptions . InheritFromBase ) != 0
113+ && ( options & AttributeSearchOptions . InheritFromAllBase ) == 0
114+ && member . GetBaseMember ( ) is MemberInfo bm ) {
115+ var attrsToAdd = GetAttributes ( bm , attributeType , options ) ;
116+ if ( attrsToAdd . Count > 0 ) {
117+ ( attributes ??= new List < Attribute > ( attrsToAdd . Count ) ) . AddRange ( attrsToAdd ) ;
118+ }
119+ }
124120 }
125- }
126- else {
127- attributes = customAttributesRaw . Cast < Attribute > ( ) ;
128- }
129121
130- if ( ( options & AttributeSearchOptions . InheritFromAllBase ) == AttributeSearchOptions . InheritFromAllBase
131- && member . DeclaringType != WellKnownTypes . Object
132- && member . GetBaseMember ( ) is MemberInfo bm2 ) {
133- var inheritedAttributes = GetAttributes ( bm2 , attributeType , options ) ;
134- count += inheritedAttributes . Count ;
135- attributes = attributes . Concat ( inheritedAttributes ) ;
122+ if ( ( options & AttributeSearchOptions . InheritFromAllBase ) != 0
123+ && member . DeclaringType != WellKnownTypes . Object
124+ && member . GetBaseMember ( ) is MemberInfo bm2 ) {
125+ var attrsToAdd = GetAttributes ( bm2 , attributeType , options ) ;
126+ if ( attrsToAdd . Count > 0 ) {
127+ ( attributes ??= new List < Attribute > ( attrsToAdd . Count ) ) . AddRange ( attrsToAdd ) ;
128+ }
129+ }
136130 }
137131
138- return ( IReadOnlyList < Attribute > ) attributes ?? Array . Empty < Attribute > ( ) ;
132+ return ( IReadOnlyList < Attribute > ) attributes ?? Array . Empty < Attribute > ( ) ;
139133 }
140134 }
141135}
0 commit comments