/////////////////////////////////////////////////////////////////////////// // Copyright (C) Wizardry and Steamworks 2013 - License: GNU GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html for legal details, // // rights of fair usage, the disclaimer and warranty conditions. // /////////////////////////////////////////////////////////////////////////// using System; using System.Collections.Generic; using System.Linq; using System.Reflection; namespace wasSharp { public static class Reflection { /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// Retrieves an attribute of type T from an enumeration. /// /// an attribute of type T public static T GetAttributeFromEnumValue(Enum value) where T : Attribute { return (T)value.GetType() .GetRuntimeField(value.ToString()) .GetCustomAttributes(typeof(T), false) .SingleOrDefault(); } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// Returns all the attributes of type T of an enumeration. /// /// the attribute to retrieve /// a list of attributes public static IEnumerable GetEnumAttributes(Enum e) where T : Attribute { return e.GetType().GetRuntimeFields().ToArray() .AsParallel() .Select(o => GetAttributeFromEnumValue((Enum)o.GetValue(Activator.CreateInstance()))); } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// Returns all the field names of an enumeration. /// /// the field names public static IEnumerable GetEnumNames() { return typeof(T).GetRuntimeFields().ToArray() .AsParallel() .Select(o => o.GetCustomAttribute(typeof(NameAttribute), false)) .Select(o => (o as NameAttribute)?.Name) .Where(o => !string.IsNullOrEmpty(o)) .Select(o => o); } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2014 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// Returns all the values of an enumeration. /// /// the values of the enumeration public static IEnumerable GetEnumValues() { return Enum.GetValues(typeof(T)).Cast().Select(value => (T)value); } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// Get the name from an enumeration value. /// /// an enumeration value /// the description or the empty string public static string GetNameFromEnumValue(Enum value) { var attribute = value.GetType() .GetRuntimeField(value.ToString()) .GetCustomAttributes(typeof(NameAttribute), false) .SingleOrDefault() as NameAttribute; return attribute?.Name; } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// Get the description from an enumeration value. /// /// an enumeration value /// the description or the empty string public static string GetDescriptionFromEnumValue(Enum value) { var attribute = value.GetType() .GetRuntimeField(value.ToString()) .GetCustomAttributes(typeof(DescriptionAttribute), false) .SingleOrDefault() as DescriptionAttribute; return attribute?.Description; } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// Get enumeration value from its name attribute. /// /// the enumeration type /// the description of a member /// the string comparison to use /// the value or the default of T if case no name attribute found public static T GetEnumValueFromName(string name, StringComparison comparison = StringComparison.OrdinalIgnoreCase) { var field = typeof(T).GetRuntimeFields().ToArray() .AsParallel().SelectMany(f => f.GetCustomAttributes( typeof(NameAttribute), false), ( f, a) => new { Field = f, Att = a }) .SingleOrDefault(a => string.Equals(((NameAttribute)a.Att) .Name, name, comparison)); return field != null ? (T)field.Field.GetValue(Activator.CreateInstance()) : default(T); } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2015 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// Get the name of a structure member. /// /// the type of the structure to search /// the structure to search /// the value of the item to search /// the description or the empty string public static string GetStructureMemberName(T structure, object item) where T : struct { var f = typeof(T).GetRuntimeFields(); var p = typeof(T).GetRuntimeProperties(); if (f != null) { var r = f.AsParallel() .SelectMany(o => o.GetCustomAttributes(typeof(NameAttribute), false), (o, a) => new { Field = o, Att = a }) .SingleOrDefault(q => q.Field.GetValue(structure).Equals(item)); if (r != null) return ((NameAttribute)r.Att).Name; } if (p != null) { var r = p.AsParallel() .SelectMany(o => o.GetCustomAttributes(typeof(NameAttribute), false), (o, a) => new { Property = o, Att = a }) .SingleOrDefault(q => q.Property.GetValue(structure).Equals(item)); if (r != null) return ((NameAttribute)r.Att).Name; } return string.Empty; } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// Get field or property from a class by supplying a path. /// /// the type of the object /// the object /// the fully qualified path to the field of property /// /// the last object in the fully qualified path or null in case the field or property could not be found /// public static object GetFP(this T o, string path) { if (string.IsNullOrEmpty(path)) return null; if (o == null) return null; var memberType = o.GetType(); var components = path.Split('.'); var f = memberType.GetRuntimeField(components[0]); var p = memberType.GetRuntimeProperty(components[0]); if (f != null) return components.Length > 1 ? GetFP(f.GetValue(o), components.Skip(1).Aggregate((a, i) => a + @"." + i)) : memberType.GetRuntimeField(path).GetValue(o); if (p != null) return components.Length > 1 ? GetFP(p.GetValue(o), components.Skip(1).Aggregate((a, i) => a + @"." + i)) : memberType.GetRuntimeProperty(path).GetValue(o); return null; } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// Get field or property info from a class by supplying a path. /// /// the type of the object /// the object /// the fully qualified path to the field of property /// /// the field or property info of the last object in the path or null if the object cannot be found /// public static object GetFPInfo(this T o, string path) { if (string.IsNullOrEmpty(path)) return null; if (o == null) return null; var memberType = o.GetType(); var components = path.Split('.'); var f = memberType.GetRuntimeField(components[0]); var p = memberType.GetRuntimeProperty(components[0]); if (f != null) return components.Length > 1 ? GetFPInfo(f.GetValue(o), components.Skip(1).Aggregate((a, i) => a + @"." + i)) : memberType.GetRuntimeField(path); if (p != null) return components.Length > 1 ? GetFPInfo(p.GetValue(o), components.Skip(1).Aggregate((a, i) => a + @"." + i)) : memberType.GetRuntimeProperty(path); return null; } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// Return all the run-time properties for an object. /// the object whose properties to return /// the property information for all the properties of the object public static IEnumerable GetPropertiesInfo(this T o) { foreach (var p in o.GetType().GetRuntimeProperties()) yield return p; } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// Return all the run-time properties for an object. /// the object whose properties to return /// the property information for all the properties of the object public static IEnumerable GetFieldsInfo(this T o) { foreach (var p in o.GetType().GetRuntimeFields()) yield return p; } /////////////////////////////////////////////////////////////////////////// // Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3 // /////////////////////////////////////////////////////////////////////////// /// /// Enumerate all the base types recursively starting from a type. /// /// the type /// an enumeration of all base types public static IEnumerable GetBaseTypes(this Type type) { var baseType = type.GetTypeInfo().BaseType; if (baseType == null) yield break; yield return baseType; foreach (var t in GetBaseTypes(baseType)) { yield return t; } } /// /// A generic name attribute. /// public class NameAttribute : Attribute { protected readonly string name; public NameAttribute(string name) { this.name = name; } public string Name => name; } /// /// A generic description attribute. /// public class DescriptionAttribute : Attribute { protected readonly string description; public DescriptionAttribute(string description) { this.description = description; } public string Description => description; } } }