/// <summary> /// Determines if the passed type passes the filter criteria or not /// </summary> /// <param name="ComparisonMode">The type comparison mode to implement</param> /// <param name="Item">The item to be evaluated</param> /// <param name="FilterItems">The collection of items that the compare item will be compared against</param> /// <param name="IsBlacklist">True if it should behave like a blacklist, false if not</param> /// <returns>True if the type is considered valid, false if not</returns> public static bool IsValidItem(TypeComparison ComparisonMode, Type Item, IEnumerable <TypeReference> FilterItems, bool IsBlacklist = true) { Func <Type, Type, bool> evaluationFunc = ComparisonMode.GetTypeComparisonDelegate(); bool foundMatch = false; foreach (TypeReference filterItem in FilterItems) { foundMatch = evaluationFunc(Item, filterItem); if (foundMatch) { break; } } if (IsBlacklist) { return(!foundMatch); } else { return(foundMatch); } }
/// <summary> /// Retrieves the function that should be used to compare two types /// based on the selected enum mode /// </summary> /// <param name="ComparisonMode">The mode to get the function for</param> /// <returns>The delegate for evaluating the two types</returns> public static Func <Type, Type, bool> GetTypeComparisonDelegate(this TypeComparison ComparisonMode) { switch (ComparisonMode) { case TypeComparison.Equals: return(CheckTypeEquality); case TypeComparison.Inherits: return(CheckTypeInherits); case TypeComparison.Implements: return(CheckTypeImplements); default: return(null); } }
/// <summary> /// Determines whether the current <see cref="Type"/> derives from the specified <see cref="Type"/>. /// </summary> /// <param name="type">The <see cref="Type"/> to check for being a subclass.</param> /// <param name="other">The <see cref="Type"/> to check for being the superclass.</param> /// <param name="comparisonMethod">The method to use when comparing two <see cref="Type"/> objects.</param> /// <returns>True if the type is a subclass, false if not.</returns> /// <exception cref="ArgumentException"><paramref name="comparisonMethod"/> is /// not a valid value in <see cref="TypeComparison"/>.</exception> /// <exception cref="ArgumentNullException"><paramref name="type"/> or <paramref name="other"/> is null.</exception> public static bool IsSubclassOf(this Type type, Type other, TypeComparison comparisonMethod) { if (type == null) { throw new ArgumentNullException(nameof(type)); } if (other == null) { throw new ArgumentNullException(nameof(other)); } switch (comparisonMethod) { case TypeComparison.Default: return(type.IsSubclassOf(other)); case TypeComparison.AssemblyQualifiedName: { var current = type; while (current != null) { if (string.Equals(current.AssemblyQualifiedName, other.AssemblyQualifiedName, StringComparison.Ordinal)) { return(true); } if (current != typeof(object)) { current = current.BaseType; } else { break; } } return(false); } default: throw new ArgumentException($"Invalid {nameof(TypeComparison)} value \"{comparisonMethod}\"!"); } }
/// <summary> /// Determines whether two <see cref="Type"/> objects represent the same type. /// </summary> /// <param name="type">The current <see cref="Type"/> to check with for equality.</param> /// <param name="other">The other <see cref="Type"/> to check against for equality.</param> /// <param name="comparisonMethod">The method to use when comparing two <see cref="Type"/> objects.</param> /// <returns>True if the types are found to be equal, false if not.</returns> /// <exception cref="ArgumentException"><paramref name="comparisonMethod"/> is /// not a valid value in <see cref="TypeComparison"/>.</exception> /// <exception cref="ArgumentNullException"><paramref name="type"/> or <paramref name="other"/> is null.</exception> public static bool Equals(this Type type, Type other, TypeComparison comparisonMethod) { if (type == null) { throw new ArgumentNullException(nameof(type)); } if (other == null) { throw new ArgumentNullException(nameof(other)); } switch (comparisonMethod) { case TypeComparison.Default: return(type.Equals(other)); case TypeComparison.AssemblyQualifiedName: return(string.Equals(type.AssemblyQualifiedName, other.AssemblyQualifiedName, StringComparison.Ordinal)); default: throw new ArgumentException($"Invalid {nameof(TypeComparison)} value \"{comparisonMethod}\"!"); } }
public static bool CompareTo <TTypes, TOtherTypes>(this TTypes types, TOtherTypes otherTypes, TypeComparison comparisonType) where TTypes : IReadOnlyList <Type> where TOtherTypes : IReadOnlyList <Type> { var count = otherTypes.Count; if (types.Count != count) { return(false); } switch (comparisonType) { case TypeComparison.Equality: for (int i = 0; i < count; ++i) { if (types[i] != otherTypes[i]) { return(false); } } return(true); case TypeComparison.AssignmentCompatibility: for (int i = 0; i < count; ++i) { if (types[i].IsAssignableFrom(otherTypes[i]) == false) { return(false); } } return(true); case TypeComparison.TypeMatchersOrElseAssignmentCompatibility: for (int i = 0; i < count; ++i) { if (types[i].IsTypeMatcher(out var typeMatcherType)) { Debug.Assert(typeMatcherType.ImplementsTypeMatcherProtocol()); var typeMatcher = (ITypeMatcher)Activator.CreateInstance(typeMatcherType); if (typeMatcher.Matches(otherTypes[i]) == false) { return(false); } } else if (types[i].IsAssignableFrom(otherTypes[i]) == false) { return(false); } } return(true); default: throw new ArgumentOutOfRangeException(nameof(comparisonType)); } }