@@ -186,17 +186,24 @@ private Tuple<Type, string> SearchForStartupAttribute(string friendlyName, IList
186186 Assembly matchedAssembly = null ;
187187 foreach ( var assembly in _referencedAssemblies )
188188 {
189- object [ ] attributes ;
189+ Attribute [ ] attributes ;
190190 try
191191 {
192- attributes = assembly . GetCustomAttributes ( inherit : false ) ;
192+ // checking attribute's name first and only then instantiating it
193+ // then we are filtering attributes by name second time as inheritors could be added by calling to GetCustomAttributes(type)
194+ attributes = assembly . GetCustomAttributesData ( )
195+ . Where ( data => MatchesStartupAttribute ( data . AttributeType ) )
196+ . Select ( data => data . AttributeType )
197+ . SelectMany ( type => assembly . GetCustomAttributes ( type ) )
198+ . Distinct ( )
199+ . ToArray ( ) ;
193200 }
194201 catch ( CustomAttributeFormatException )
195202 {
196203 continue ;
197204 }
198-
199- foreach ( var owinStartupAttribute in attributes . Where ( attribute => attribute . GetType ( ) . Name . Equals ( Constants . OwinStartupAttribute , StringComparison . Ordinal ) ) )
205+
206+ foreach ( var owinStartupAttribute in attributes . Where ( attribute => MatchesStartupAttribute ( attribute . GetType ( ) ) ) )
200207 {
201208 Type attributeType = owinStartupAttribute . GetType ( ) ;
202209 foundAnyInstances = true ;
@@ -265,6 +272,11 @@ private Tuple<Type, string> SearchForStartupAttribute(string friendlyName, IList
265272 }
266273 return fullMatch ;
267274 }
275+
276+ private static bool MatchesStartupAttribute ( Type type )
277+ {
278+ return type . Name . Equals ( Constants . OwinStartupAttribute , StringComparison . Ordinal ) ;
279+ }
268280
269281 // Search for any assemblies with a Startup or [AssemblyName].Startup class.
270282 private Tuple < Type , string > SearchForStartupConvention ( IList < string > errors )
0 commit comments