#region CPL License /* Nuclex Framework Copyright (C) 2002-2017 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #endregion using System; using System.Collections.Generic; using System.Reflection; namespace Nuclex.Support { /// Helper methods for the reflection Type class public static class TypeHelper { #region class FieldInfoComparer /// Determines whether member informations relate to the same member private class FieldInfoComparer : IEqualityComparer { /// Default instance of the comparer public static readonly FieldInfoComparer Default = new FieldInfoComparer(); /// Checks whether two member informations are equal /// Informations about the left member in the comaprison /// Informations about the right member in the comparison /// True if the two member informations relate to the same member public bool Equals(FieldInfo left, FieldInfo right) { return (left.DeclaringType == right.DeclaringType) && (left.Name == right.Name); } /// Determines the hash code of the specified member informations /// /// Member informations whose hash code will be determined /// /// The hash code of the specified member informations public int GetHashCode(FieldInfo FieldInfo) { return (FieldInfo.DeclaringType.GetHashCode() ^ FieldInfo.Name.GetHashCode()); } } #endregion // class MemberInfoComparer /// /// Returns all the fields of a type, including those defined in the type's base classes /// /// Type whose fields will be returned /// Binding flags to use when querying the fields /// All of the type's fields, including its base types public static FieldInfo[] GetFieldInfosIncludingBaseClasses( this Type type, BindingFlags bindingFlags ) { FieldInfo[] fieldInfos = type.GetFields(bindingFlags); // If this class doesn't have a base, don't waste any time if(type.BaseType != typeof(object)) { var fieldInfoSet = new Dictionary(FieldInfoComparer.Default); for(int index = 0; index < fieldInfos.Length; ++index) { fieldInfoSet.Add(fieldInfos[index], null); } while(type.BaseType != typeof(object)) { type = type.BaseType; fieldInfos = type.GetFields(bindingFlags); for(int index = 0; index < fieldInfos.Length; ++index) { addIfNotExists(fieldInfoSet, fieldInfos[index]); } } fieldInfos = new FieldInfo[fieldInfoSet.Count]; fieldInfoSet.Keys.CopyTo(fieldInfos, 0); } return fieldInfos; } /// Determines whether the given type has a default constructor /// Type which is to be checked /// True if the type has a default constructor public static bool HasDefaultConstructor(this Type type) { ConstructorInfo[] constructors = type.GetConstructors(); for(int index = 0; index < constructors.Length; ++index) { ConstructorInfo constructor = constructors[index]; if(constructor.IsPublic && (constructor.GetParameters().Length == 0)) { return true; } } return false; } /// Determines whether the type has the specified attribute /// Attribute the type will be checked for /// /// Type that will be checked for presence of the specified attribute /// /// True if the type has the specified attribute, otherwise false public static bool HasAttribute(this Type type) { return type.HasAttribute(typeof(TAttribute)); } /// Determines whether the type has the specified attribute /// /// Type that will be checked for presence of the specified attribute /// /// Attribute the type will be checked for /// True if the type has the specified attribute, otherwise false public static bool HasAttribute(this Type type, Type attributeType) { object[] attributes = type.GetCustomAttributes(attributeType, true); return (attributes != null) && (attributes.Length > 0); } /// /// Adds field informations to a list if they're not already contained in it /// /// List the field informations will be added to /// Field informations that will be added to the list private static void addIfNotExists( IDictionary fieldInfos, FieldInfo fieldInfo ) { if(!fieldInfos.ContainsKey(fieldInfo)) { fieldInfos.Add(fieldInfo, null); } } } } // namespace Nuclex.Support