/// <summary> /// Determines whether the specified type reference implements directly or indirectly a requested marker interface. /// </summary> /// <param name="typeReference">The type reference.</param> /// <param name="markerInterface">The aspect marker interface.</param> /// <returns></returns> private bool IsMarker(ITypeDefOrRef typeReference, ITypeDefOrRef markerInterface) { if (typeReference is null) { return(false); } lock (_isMarker) { var key = Tuple.Create(typeReference.FullName, markerInterface.FullName); // there is a cache, because the same attribute may be found several time // and we’re in a hurry, the developer is waiting for his program to start! if (_isMarker.TryGetValue(key, out var isMarker)) { return(isMarker); } // otherwise look for type or implemented interfaces (recursively) var typeDef = ResolveTypeOrGenericDefinition(typeReference); if (typeDef is null) { return(false); } var interfaces = typeDef.Interfaces; _isMarker[key] = isMarker = typeReference.SafeEquivalent(markerInterface) || interfaces.Any(i => IsMarker(i.Interface, markerInterface)) || IsMarker(typeDef.BaseType, markerInterface); return(isMarker); } }