diff --git a/X10D/src/ExceptionMessages.cs b/X10D/src/ExceptionMessages.cs new file mode 100644 index 0000000..789e273 --- /dev/null +++ b/X10D/src/ExceptionMessages.cs @@ -0,0 +1,11 @@ +using System; + +namespace X10D +{ + internal static class ExceptionMessages + { + public static readonly string TypeDoesNotInheritAttribute = $"{{0}} does not inherit {typeof(Attribute)}"; + public static readonly string TypeIsNotClass = $"{{0}} is not a class"; + public static readonly string TypeIsNotInterface = $"{{0}} is not an interface"; + } +} diff --git a/X10D/src/ReflectionExtensions.cs b/X10D/src/ReflectionExtensions.cs deleted file mode 100644 index 4e87200..0000000 --- a/X10D/src/ReflectionExtensions.cs +++ /dev/null @@ -1,123 +0,0 @@ -using System; -using System.ComponentModel; -using System.Reflection; - -namespace X10D -{ - /// - /// Extension methods for various reflection types. - /// - public static class ReflectionExtensions - { - /// - /// Gets the value set in this member's annotated , or - /// if none exists. - /// - /// The member. - /// - /// Returns an representing the value stored in this member's - /// . - /// - /// is . - public static object GetDefaultValue(this MemberInfo member) - { - if (member is null) - { - throw new ArgumentNullException(nameof(member)); - } - - if (!(member.GetCustomAttribute() is { } attribute)) - { - return default; - } - - return attribute.Value; - } - - /// - /// Gets the value set in this member's annotated , or - /// if none exists. - /// - /// The type to which the value should cast. - /// The member. - /// - /// Returns an instance of representing the value stored in this member's - /// . - /// - /// is . - public static T GetDefaultValue(this MemberInfo member) - { - if (member is null) - { - throw new ArgumentNullException(nameof(member)); - } - - return (T)member.GetDefaultValue(); - } - - /// - /// Gets the value set in this member's annotated , or - /// if none exists. - /// - /// The member. - /// - /// Returns a string representing the value stored in this member's - /// . - /// - /// is . - public static string GetDescription(this MemberInfo member) - { - if (member is null) - { - throw new ArgumentNullException(nameof(member)); - } - - if (!(member.GetCustomAttribute() is { } attribute)) - { - return null; - } - - return attribute.Description; - } - - /// - /// Retrieves a custom attribute of a specified type that is applied to the specified member, and passes it - /// to a selector delegate in order to select one or more the members in the attribute. - /// - /// The attribute type. - /// The return type of the delegate. - /// The member. - /// The selector delegate. - /// - /// Returns an instance of as provided from - /// . - /// - /// - /// is - /// -or- - /// is . - /// - public static TReturn SelectFromCustomAttribute( - this MemberInfo member, - Func selector) - where TAttribute : Attribute - { - if (member is null) - { - throw new ArgumentNullException(nameof(member)); - } - - if (selector is null) - { - throw new ArgumentNullException(nameof(selector)); - } - - if (!(member.GetCustomAttribute() is { } attribute)) - { - return default; - } - - return selector(attribute); - } - } -} diff --git a/X10D/src/ReflectionExtensions/MemberInfoExtensions.cs b/X10D/src/ReflectionExtensions/MemberInfoExtensions.cs new file mode 100644 index 0000000..b6c57bd --- /dev/null +++ b/X10D/src/ReflectionExtensions/MemberInfoExtensions.cs @@ -0,0 +1,98 @@ +using System; +using System.Globalization; +using System.Reflection; + +namespace X10D.ReflectionExtensions +{ + /// + /// Extension methods for . + /// + public static class MemberInfoExtensions + { + /// + /// Returns a value indicating whether or not the current member has been decorated with a specified attribute. + /// + /// The member attributes to check. + /// The attribute type. + /// + /// if the current member has been decorated with a specified attribute, or + /// otherwise. + /// + /// is . + public static bool HasCustomAttribute(this MemberInfo member) + where T : Attribute + { + if (member is null) + { + throw new ArgumentNullException(nameof(member)); + } + + return member.HasCustomAttribute(typeof(T)); + } + + /// + /// Returns a value indicating whether or not the current member has been decorated with a specified attribute. + /// + /// The member attributes to check. + /// The attribute type. + /// + /// if the current member has been decorated with a specified attribute, or + /// otherwise. + /// + /// is . + public static bool HasCustomAttribute(this MemberInfo member, Type attribute) + { + if (member is null) + { + throw new ArgumentNullException(nameof(member)); + } + + if (attribute is null) + { + throw new ArgumentNullException(nameof(attribute)); + } + + if (!attribute.Inherits()) + { + throw new ArgumentException( + string.Format(CultureInfo.CurrentCulture, ExceptionMessages.TypeDoesNotInheritAttribute, attribute), + nameof(attribute)); + } + + return member.GetCustomAttribute(attribute) is not null; + } + + /// + /// Retrieves a custom attribute that is decorated by the current member, and projects it into to a new form. + /// + /// The attribute type. + /// The return type of the delegate. + /// The member. + /// A transform function to apply to the attribute. + /// + /// An instance of as provided from . + /// + /// + /// is + /// -or- + /// is . + /// + public static TReturn? SelectFromCustomAttribute(this MemberInfo type, Func selector) + where TAttribute : Attribute + { + if (type is null) + { + throw new ArgumentNullException(nameof(type)); + } + + if (selector is null) + { + throw new ArgumentNullException(nameof(selector)); + } + + return type.GetCustomAttribute() is { } attribute + ? selector(attribute) + : default; + } + } +} diff --git a/X10D/src/ReflectionExtensions/TypeExtensions.cs b/X10D/src/ReflectionExtensions/TypeExtensions.cs new file mode 100644 index 0000000..f72ce83 --- /dev/null +++ b/X10D/src/ReflectionExtensions/TypeExtensions.cs @@ -0,0 +1,190 @@ +using System; +using System.Globalization; +using System.Reflection; + +namespace X10D.ReflectionExtensions +{ + /// + /// Extension methods for . + /// + public static class TypeExtensions + { + /// + /// Returns a value indicating whether or not the current type has been decorated with a specified attribute. + /// + /// The type whose attributes to check. + /// The attribute type. + /// + /// if the current type has been decorated with a specified attribute, or + /// otherwise. + /// + /// is . + public static bool HasCustomAttribute(this Type type) + where T : Attribute + { + if (type is null) + { + throw new ArgumentNullException(nameof(type)); + } + + return type.HasCustomAttribute(typeof(T)); + } + + /// + /// Returns a value indicating whether or not the current type has been decorated with a specified attribute. + /// + /// The type whose attributes to check. + /// The attribute type. + /// + /// if the current type has been decorated with a specified attribute, or + /// otherwise. + /// + /// is . + public static bool HasCustomAttribute(this Type type, Type attribute) + { + if (type is null) + { + throw new ArgumentNullException(nameof(type)); + } + + if (attribute is null) + { + throw new ArgumentNullException(nameof(attribute)); + } + + if (!attribute.Inherits()) + { + throw new ArgumentException( + string.Format(CultureInfo.CurrentCulture, ExceptionMessages.TypeDoesNotInheritAttribute, attribute), + nameof(attribute)); + } + + return type.GetCustomAttribute(attribute) is not null; + } + + /// + /// Returns a value indicating whether the current type implements a specified interface. + /// + /// The type whose interface list to check. + /// The interface type. + /// if the current exists on the type, or otherwise. + public static bool Implements(this Type value) + { + return value.Implements(typeof(T)); + } + + /// + /// Returns a value indicating whether the current type implements a specified interface. + /// + /// The type whose interface list to check. + /// The interface type. + /// if the current exists on the type, or otherwise. + public static bool Implements(this Type value, Type interfaceType) + { + if (value is null) + { + throw new ArgumentNullException(nameof(value)); + } + + if (interfaceType is null) + { + throw new ArgumentNullException(nameof(interfaceType)); + } + + if (!interfaceType.IsInterface) + { + throw new ArgumentException( + string.Format(CultureInfo.CurrentCulture, ExceptionMessages.TypeIsNotInterface, interfaceType), + nameof(interfaceType)); + } + + return Array.IndexOf(value.GetInterfaces(), interfaceType) >= 0; + } + + /// + /// Returns a value indicating whether the current type inherits a specified type. + /// + /// The type whose interface list to check. + /// The base type. + /// + /// if the current type inherits , or + /// otherwise. + /// + public static bool Inherits(this Type value) + where T : class + { + return value.Inherits(typeof(T)); + } + + /// + /// Returns a value indicating whether the current type inherits a specified type. + /// + /// The type whose interface list to check. + /// The base type. + /// + /// if the current type inherits , or + /// otherwise. + /// + public static bool Inherits(this Type value, Type type) + { + if (value is null) + { + throw new ArgumentNullException(nameof(value)); + } + + if (type is null) + { + throw new ArgumentNullException(nameof(type)); + } + + if (!value.IsClass) + { + throw new ArgumentException( + string.Format(CultureInfo.CurrentCulture, ExceptionMessages.TypeIsNotClass, value), + nameof(value)); + } + + if (!type.IsClass) + { + throw new ArgumentException( + string.Format(CultureInfo.CurrentCulture, ExceptionMessages.TypeIsNotClass, type), + nameof(type)); + } + + return value.IsSubclassOf(type); + } + + /// + /// Retrieves a custom attribute that is decorated by the current type, and projects it into to a new form. + /// + /// The attribute type. + /// The return type of the delegate. + /// The type. + /// A transform function to apply to the attribute. + /// + /// An instance of as provided from . + /// + /// + /// is + /// -or- + /// is . + /// + public static TReturn? SelectFromCustomAttribute(this Type type, Func selector) + where TAttribute : Attribute + { + if (type is null) + { + throw new ArgumentNullException(nameof(type)); + } + + if (selector is null) + { + throw new ArgumentNullException(nameof(selector)); + } + + return type.GetCustomAttribute() is { } attribute + ? selector(attribute) + : default; + } + } +}