namespace jeanf.propertyDrawer { using System; using System.Linq; using System.Reflection; using System.Collections; using System.Collections.Generic; public static class ReflectionUtil { private static Assembly[] _allAssemblies; public static Assembly[] AllAssemblies { get { if (_allAssemblies == null) { _allAssemblies = AppDomain.CurrentDomain.GetAssemblies(); } return _allAssemblies; } } public static IEnumerable GetAllTypesWithAttributeAsEnumerable(this Assembly assembly, Type attribute) { foreach (Type type in assembly.GetTypes()) { if (type.GetCustomAttributes(attribute.GetType(), true).Length > 0) { yield return type; } } } public static Type[] GetAllTypesWithAttribute(this Assembly assembly, Type attribute) { return assembly.GetAllTypesWithAttributeAsEnumerable(attribute).ToArray(); } /// /// Finds the most nested object inside of an object. /// /// /// /// /// public static T GetNestedObject(this object obj, string path) { foreach (string part in path.Split('.')) { obj = obj.GetFieldOrProperty(part); } return (T)obj; } #region Get Variable Methods /// /// Gets a property or a field of an object by a name. /// /// Type of the field/property. /// Object the field/property should be found in. /// Name of the field/property. /// Filters for the field/property it can find. (optional) /// The field/property. public static T GetFieldOrProperty(this object obj, string name, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) { try { // Try getting the field. If the property wasn't found... return GetField(obj, name, bindingFlags); } catch (FieldNotFoundException) { //...try getting the property. If that wasn't found as well, throw an exception try { return GetProperty(obj, name, bindingFlags); } catch (PropertyNotFoundException) { throw new PropertyOrFieldNotFoundException("Couldn't find a filed nor a property with the name of '" + name + "' inside of the object '" + obj.GetType().Name + "'"); } } } /// /// Gets a field inside of an object by a name. /// /// Type of the field. /// Object the field should be found in. /// Name of the field. /// Filters for the fields it can find. (optional) /// The field. public static T GetField(this object obj, string name, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) { // Try getting the field and returning it. FieldInfo field = obj.GetType().GetField(name, bindingFlags); if (field != null) return (T)field.GetValue(obj); // If a field couldn't be found. Throw an exception about it. throw new FieldNotFoundException("Couldn't find a field with the name of '" + name + "' inside of the object '" + obj.GetType().Name + "'"); } /// /// Gets a property inside of an object by a name. /// /// Type of the property. /// Object the property should be found in. /// Name of the property. /// Filters for the properties it can find. (optional) /// The property. public static T GetProperty(this object obj, string name, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) { // Try getting the field and returning it. PropertyInfo property = obj.GetType().GetProperty(name, bindingFlags); if (property != null) return (T)property.GetValue(obj, null); // If a field couldn't be found. Throw an exception about it. throw new PropertyNotFoundException("Couldn't find a property with the name of '" + name + "' inside of the object '" + obj.GetType().Name + "'"); } #endregion #region Set Variable Methods /// /// Sets a field or a property inside of an object by name. /// /// Type of the field/property. /// Object contaning the field/property. /// Name of the field/property. /// New value of the field/property. /// Filters for the field/property it can find. (optional) public static void SetFieldOrProperty(this object obj, string name, T value, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) { try { // Try getting the field. If the property wasn't found... SetField(obj, name, value, bindingFlags); return; } catch (FieldNotFoundException) { //...try getting the property. If that wasn't found as well, throw an exception try { SetProperty(obj, name, value, bindingFlags); return; } catch (PropertyNotFoundException) { throw new PropertyOrFieldNotFoundException("Couldn't find a filed nor a property with the name of '" + name + "' inside of the object '" + obj.GetType().Name + "'"); } } } /// /// Sets a field inside of an object by name. /// /// Type of the field. /// Object contaning the field. /// Name of the field. /// New value of the field.Filters for the fields it can find. (optional)> public static void SetField(this object obj, string name, T value, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) { // Try getting the field and returning it. FieldInfo field = obj.GetType().GetField(name, bindingFlags); if (field != null) { field.SetValue(obj, value); return; } // If a field couldn't be found. Throw an exception about it. throw new FieldNotFoundException("Couldn't find a field with the name of '" + name + "' inside of the object '" + obj.GetType().Name + "'"); } /// /// Sets a property inside of an object by name. /// /// Type of the property. /// Object contaning the property. /// Name of the property. /// New value of the property. /// Filters for the properties it can find. (optional) public static void SetProperty(this object obj, string name, T value, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) { // Try getting the field and returning it. PropertyInfo property = obj.GetType().GetProperty(name, bindingFlags); if (property != null) { property.SetValue(obj, value, null); return; } // If a field couldn't be found. Throw an exception about it. throw new PropertyNotFoundException("Couldn't find a property with the name of '" + name + "' inside of the object '" + obj.GetType().Name + "'"); } #endregion #region Get All Variables Methods /// /// Gets all the properties and fields in obj of type T. /// /// The type of the fields/properties. /// Object to find the fields/properties in. /// Filters for the types of fields/properties that can be found. /// The fields/properties found. public static IEnumerable GetAllFieldsOrProperties(this object obj, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) { // Get the fields and the properties in the object. T[] fields = obj.GetAllFields(bindingFlags).ToArray(); T[] properties = obj.GetAllProperties(bindingFlags).ToArray(); // Only return the fields if fields were found. if (fields != null && fields.Length != 0) { // Loop through the fields and return each one. for (int i = 0; i < fields.Length; i++) { yield return fields[i]; } } // Only return the properties if properties were found. if (properties != null && properties.Length != 0) { // Loop through the properties and return each one if they have the right type. for (int i = 0; i < properties.Length; i++) { yield return properties[i]; } } } /// /// Gets all the properties and fields in obj. /// /// Object to find the fields/properties in. /// Filters for the types of fields/properties that can be found. /// The fields/properties found. public static IEnumerable GetAllFieldsOrProperties(this object obj, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) { // Get the fields and the properties in the object. object[] fields = obj.GetAllFields(bindingFlags).Cast().ToArray(); object[] properties = obj.GetAllProperties(bindingFlags).Cast().ToArray(); // Only return the fields if fields were found. if (fields != null && fields.Length != 0) { // Loop through the fields and return each one. for (int i = 0; i < fields.Length; i++) { yield return fields[i]; } } // Only return the properties if properties were found. if (properties != null && properties.Length != 0) { // Loop through the properties and return each one if they have the right type. for (int i = 0; i < properties.Length; i++) { yield return properties[i]; } } } /// /// Gets all the fields in obj of type T. /// /// Type of the fields allowed. /// Object to find the fields in. /// Filters of the fields allowed. /// The fields found. public static IEnumerable GetAllFields(this object obj, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) { // Get all the properties. FieldInfo[] fields = obj.GetType().GetFields(bindingFlags); // If there are no properties, break. if (fields == null || fields.Length == 0) yield break; // If there are properties in the array, return each element. for (int i = 0; i < fields.Length; i++) { object currentValue = fields[i].GetValue(obj); if (currentValue.GetType() == typeof(T)) yield return (T)currentValue; } } /// /// Gets all the fields in obj. /// /// Object to find the fields in. /// Filters of the fields allowed. /// The fields found. public static IEnumerable GetAllFields(this object obj, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) { // Get all the properties. FieldInfo[] fields = obj.GetType().GetFields(bindingFlags); // If there are no properties, break. if (fields == null || fields.Length == 0) yield break; // If there are properties in the array, return each element. for (int i = 0; i < fields.Length; i++) { yield return fields[i].GetValue(obj); } } /// /// Gets all the properties in obj of type T. /// /// Type of the properties allowed. /// Object to find the properties in. /// Filters of the properties allowed. /// The properties found. public static IEnumerable GetAllProperties(this object obj, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) { // Get all the properties. PropertyInfo[] properties = obj.GetType().GetProperties(bindingFlags); // If there are no properties, break. if (properties == null || properties.Length == 0) yield break; // If there are properties in the array, return each element. for (int i = 0; i < properties.Length; i++) { object currentValue = properties[i].GetValue(obj, null); if (currentValue.GetType() == typeof(T)) yield return (T)currentValue; } } /// /// Gets all the properties in obj. /// /// Object to find the properties in. /// Filters of the properties allowed. /// The properties found. public static IEnumerable GetAllProperties(this object obj, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) { // Get all the properties. PropertyInfo[] properties = obj.GetType().GetProperties(bindingFlags); // If there are no properties, break. if (properties == null || properties.Length == 0) yield break; // If there are properties in the array, return each element. for (int i = 0; i < properties.Length; i++) { yield return properties[i].GetValue(obj, null); } } #endregion } }