diff --git a/src/Owin.Loader/DefaultLoader.cs b/src/Owin.Loader/DefaultLoader.cs index cf1621ec..e09e2725 100644 --- a/src/Owin.Loader/DefaultLoader.cs +++ b/src/Owin.Loader/DefaultLoader.cs @@ -186,17 +186,24 @@ private Tuple SearchForStartupAttribute(string friendlyName, IList Assembly matchedAssembly = null; foreach (var assembly in _referencedAssemblies) { - object[] attributes; + Attribute[] attributes; try { - attributes = assembly.GetCustomAttributes(inherit: false); + // checking attribute's name first and only then instantiating it + // then we are filtering attributes by name second time as inheritors could be added by calling to GetCustomAttributes(type) + attributes = assembly.GetCustomAttributesData() + .Where(data => MatchesStartupAttribute(data.AttributeType)) + .Select(data => data.AttributeType) + .SelectMany(type => assembly.GetCustomAttributes(type)) + .Distinct() + .ToArray(); } catch (CustomAttributeFormatException) { continue; } - - foreach (var owinStartupAttribute in attributes.Where(attribute => attribute.GetType().Name.Equals(Constants.OwinStartupAttribute, StringComparison.Ordinal))) + + foreach (var owinStartupAttribute in attributes.Where(attribute => MatchesStartupAttribute(attribute.GetType()))) { Type attributeType = owinStartupAttribute.GetType(); foundAnyInstances = true; @@ -265,6 +272,11 @@ private Tuple SearchForStartupAttribute(string friendlyName, IList } return fullMatch; } + + private static bool MatchesStartupAttribute(Type type) + { + return type.Name.Equals(Constants.OwinStartupAttribute, StringComparison.Ordinal); + } // Search for any assemblies with a Startup or [AssemblyName].Startup class. private Tuple SearchForStartupConvention(IList errors)