#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