using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using Developpez.Dotnet.Properties; namespace Developpez.Dotnet.Reflection { /// /// Fournit des méthodes d'extension pour faciliter l'utilisation de la réflexion /// public static class ReflectionExtensions { #region Type extensions /// /// Détermine si un type hérite d'un autre type, ou implémente une interface /// /// Le type à vérifier /// Le type de base dont type doit hériter /// true si type est superType, hérite de superType, ou implémente superType. Sinon, false public static bool Is(this Type type, Type superType) { return superType.IsAssignableFrom(type); } /// /// Détermine si un type hérite d'un autre type, ou implémente une interface /// /// Le type de base dont type doit hériter /// Le type à vérifier /// true si type est T, hérite de T, ou implémente T. Sinon, false public static bool Is(this Type type) { return type.Is(typeof(T)); } /// /// Vérifie si type est implicitement convertible à partir de sourceType. /// /// Type cible /// Type source /// true s'il existe une conversion implicite de sourceType vers type, ou si aucune conversion n'est nécessaire ; sinon, false. public static bool IsImplicitlyConvertibleFrom(this Type type, Type sourceType) { return type.IsConvertibleFrom(sourceType, ConversionType.Implicit); } /// /// Vérifie si type est implicitement convertible à partir de T. /// /// Type source /// Type cible /// true s'il existe une conversion implicite de T vers type, ou si aucune conversion n'est nécessaire ; sinon, false. public static bool IsImplicitlyConvertibleFrom(this Type type) { return type.IsImplicitlyConvertibleFrom(typeof (T)); } /// /// Vérifie si type est convertible (implicitement ou explicitement) à partir de sourceType. /// /// Type cible /// Type source /// true s'il existe une conversion (implicite ou explicite) de sourceType vers type, ou si aucune conversion n'est nécessaire ; sinon, false. public static bool IsConvertibleFrom(this Type type, Type sourceType) { return type.IsConvertibleFrom(sourceType, ConversionType.Any); } /// /// Vérifie si type est convertible (implicitement ou explicitement) à partir de T. /// /// Type source /// Type cible /// true s'il existe une conversion (implicite ou explicite) de T vers type, ou si aucune conversion n'est nécessaire ; sinon, false. public static bool IsConvertibleFrom(this Type type) { return type.IsConvertibleFrom(typeof(T)); } /// /// Vérifie si type est implicitement convertible en targetType. /// /// Type source /// Type cible /// true s'il existe une conversion implicite de type vers T, ou si aucune conversion n'est nécessaire ; sinon, false. public static bool IsImplicitlyConvertibleTo(this Type type, Type targetType) { return targetType.IsConvertibleFrom(type, ConversionType.Implicit); } /// /// Vérifie si type est implicitement convertible en T. /// /// Type cible /// Type source /// true s'il existe une conversion implicite de type vers targetType, ou si aucune conversion n'est nécessaire ; sinon, false. public static bool IsImplicitlyConvertibleTo(this Type type) { return type.IsImplicitlyConvertibleTo(typeof(T)); } /// /// Vérifie si type est convertible (implicitement ou explicitement) en targetType. /// /// Type source /// Type cible /// true s'il existe une conversion (implicite ou explicite) de type vers targetType, ou si aucune conversion n'est nécessaire ; sinon, false. public static bool IsConvertibleTo(this Type type, Type targetType) { return targetType.IsConvertibleFrom(type, ConversionType.Any); } /// /// Vérifie si type est convertible (implicitement ou explicitement) en T. /// /// Type cible /// Type source /// true s'il existe une conversion (implicite ou explicite) de type vers targetType, ou si aucune conversion n'est nécessaire ; sinon, false. public static bool IsConvertibleTo(this Type type) { return type.IsConvertibleTo(typeof(T)); } private enum ConversionType { Explicit, Implicit, Any } private static bool IsConvertibleFrom(this Type type, Type sourceType, ConversionType conversionType) { return type.IsAssignableFrom(sourceType) || type.HasCustomConversionFrom(sourceType, conversionType) || sourceType.HasCustomConversionTo(type, conversionType); } private static bool HasCustomConversionFrom(this Type type, Type sourceType, ConversionType conversionType) { string operatorName; switch (conversionType) { case ConversionType.Explicit: operatorName = "op_Explicit"; break; case ConversionType.Implicit: operatorName = "op_Implicit"; break; case ConversionType.Any: return type.HasCustomConversionFrom(sourceType, ConversionType.Implicit) || type.HasCustomConversionFrom(sourceType, ConversionType.Explicit); default: throw new ArgumentException(ExceptionMessages.UnknownConversionType, "conversionType"); } return type.GetMethod(operatorName, new[] { sourceType }) != null; } private static bool HasCustomConversionTo(this Type type, Type targetType, ConversionType conversionType) { string operatorName; switch (conversionType) { case ConversionType.Explicit: operatorName = "op_Explicit"; break; case ConversionType.Implicit: operatorName = "op_Implicit"; break; case ConversionType.Any: return type.HasCustomConversionTo(targetType, ConversionType.Implicit) || type.HasCustomConversionTo(targetType, ConversionType.Explicit); default: throw new ArgumentException(ExceptionMessages.UnknownConversionType, "conversionType"); } return type.GetMethods() .Where(m => m.Name == operatorName && m.ReturnType == targetType) .Any(); } /// /// Indique si un type est nullable. /// /// Type dont on veut vérifier s'il est nullable /// true si type est un type référence ou un type générique Nullable<T>, false sinon public static bool IsNullable(this Type type) { if (type.IsValueType) { return type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>); } return true; } /// /// Renvoie la valeur par défaut du type spécifié /// /// Le type dont on veut récupérer la valeur par défaut /// La valeur par défaut du type public static object GetDefaultValue(this Type type) { if (type.IsValueType && type != typeof(void)) return Activator.CreateInstance(type); return null; } /// /// Indique si un type est statique. /// /// Le type à tester /// true si le type est statique, false sinon public static bool IsStatic(this Type type) { return type.IsAbstract && type.IsSealed; } #endregion #region ICustomAttributeProvider extensions /// /// Détermine si un attribut est appliqué à un objet de réflexion. /// /// L'objet de réflexion à vérifier /// Le type de l'attribut à rechercher /// true si l'attribut spécifié est appliqué à l'objet de réflexion, false sinon public static bool HasAttribute(this ICustomAttributeProvider reflectionObject, Type attributeType) { return reflectionObject.IsDefined(attributeType, true); } /// /// Détermine si un attribut est appliqué à un objet de réflexion. /// /// L'objet de réflexion à vérifier /// Le type de l'attribut à rechercher /// true pour rechercher aussi dans les ancêtres, false sinon /// true si l'attribut spécifié est appliqué à l'objet de réflexion, false sinon public static bool HasAttribute(this ICustomAttributeProvider reflectionObject, Type attributeType, bool inherit) { return reflectionObject.IsDefined(attributeType, inherit); } /// /// Récupère les attributs appliqués à un objet de réflexion. /// /// L'objet de réflexion dont on veut récupérer les attributs /// Une liste des attributs appliqués à l'objet de réflexion public static IEnumerable GetAttributes(this ICustomAttributeProvider reflectionObject) { return reflectionObject.GetAttributes(true); } /// /// Récupère les attributs appliqués à un objet de réflexion. /// /// L'objet de réflexion dont on veut récupérer les attributs /// true pour rechercher aussi dans les ancêtres, false sinon /// Une liste des attributs du type demandé appliqués à l'objet de réflexion public static IEnumerable GetAttributes(this ICustomAttributeProvider reflectionObject, bool inherit) { return reflectionObject.GetCustomAttributes(inherit).Cast(); } /// /// Récupère les attributs appliqués à un objet de réflexion. /// /// L'objet de réflexion dont on veut récupérer les attributs /// Le type de l'attribut recherché /// Une liste des attributs du type demandé appliqués à l'objet de réflexion public static IEnumerable GetAttributes(this ICustomAttributeProvider reflectionObject, Type attributeType) { return reflectionObject.GetAttributes(attributeType, true); } /// /// Récupère les attributs appliqués à un objet de réflexion. /// /// L'objet de réflexion dont on veut récupérer les attributs /// Le type de l'attribut recherché /// true pour rechercher aussi dans les ancêtres, false sinon /// Une liste des attributs du type demandé appliqués à l'objet de réflexion public static IEnumerable GetAttributes(this ICustomAttributeProvider reflectionObject, Type attributeType, bool inherit) { return reflectionObject.GetCustomAttributes(attributeType, inherit).Cast(); } /// /// Récupère un attribut appliqué à un objet de réflexion. /// /// L'objet de réflexion dont on veut récupérer un attribut /// Le type de l'attribut recherché /// L'attribut recherché s'il existe, null sinon public static Attribute GetAttribute(this ICustomAttributeProvider reflectionObject, Type attributeType) { return reflectionObject.GetAttribute(attributeType, true); } /// /// Récupère un attribut appliqué à un objet de réflexion. /// /// L'objet de réflexion dont on veut récupérer un attribut /// Le type de l'attribut recherché /// true pour rechercher aussi dans les ancêtres, false sinon /// L'attribut recherché s'il existe, null sinon public static Attribute GetAttribute(this ICustomAttributeProvider reflectionObject, Type attributeType, bool inherit) { return reflectionObject.GetCustomAttributes(attributeType, inherit).Cast().FirstOrDefault(); } /// /// Détermine si un attribut est appliqué à un objet de réflexion. /// /// Le type de l'attribut à rechercher /// L'objet de réflexion à vérifier /// true si l'attribut spécifié est appliqué à l'objet de réflexion, false sinon public static bool HasAttribute(this ICustomAttributeProvider reflectionObject) where T : Attribute { return reflectionObject.HasAttribute(typeof(T)); } /// /// Détermine si un attribut est appliqué à un objet de réflexion. /// /// Le type de l'attribut à rechercher /// L'objet de réflexion à vérifier /// true pour rechercher aussi dans les ancêtres, false sinon /// true si l'attribut spécifié est appliqué à l'objet de réflexion, false sinon public static bool HasAttribute(this ICustomAttributeProvider reflectionObject, bool inherit) where T : Attribute { return reflectionObject.HasAttribute(typeof(T), inherit); } /// /// Récupère les attributs appliqués à un objet de réflexion. /// /// Le type de l'attribut recherché /// L'objet de réflexion dont on veut récupérer les attributs /// Une liste des attributs du type demandé appliqués à l'objet de réflexion public static IEnumerable GetAttributes(this ICustomAttributeProvider reflectionObject) where T : Attribute { return reflectionObject.GetAttributes(typeof(T)).Cast(); } /// /// Récupère les attributs appliqués à un objet de réflexion. /// /// Le type de l'attribut recherché /// L'objet de réflexion dont on veut récupérer les attributs /// true pour rechercher aussi dans les ancêtres, false sinon /// Une liste des attributs du type demandé appliqués à l'objet de réflexion public static IEnumerable GetAttributes(this ICustomAttributeProvider reflectionObject, bool inherit) where T : Attribute { return reflectionObject.GetAttributes(typeof(T), inherit).Cast(); } /// /// Récupère un attribut appliqué à un objet de réflexion. /// /// Le type de l'attribut recherché /// L'objet de réflexion dont on veut récupérer un attribut /// L'attribut recherché s'il existe, null sinon public static T GetAttribute(this ICustomAttributeProvider reflectionObject) where T : Attribute { return reflectionObject.GetAttribute(typeof(T)) as T; } /// /// Récupère un attribut appliqué à un objet de réflexion. /// /// Le type de l'attribut recherché /// L'objet de réflexion dont on veut récupérer un attribut /// true pour rechercher aussi dans les ancêtres, false sinon /// L'attribut recherché s'il existe, null sinon public static T GetAttribute(this ICustomAttributeProvider reflectionObject, bool inherit) where T : Attribute { return reflectionObject.GetAttribute(typeof(T), inherit) as T; } #endregion #region PropertyInfo extensions /// /// Définit la valeur d'une propriété pour un objet. Equivalent à PropertyInfo.GetValue, /// mais fonctionne aussi pour les types valeur. /// /// Type de l'objet /// Descripteur de la propriété /// objet pour lequel on définit la valeur de la propriété /// Nouvelle valeur de la propriété public static void SetValue(this PropertyInfo propertyInfo, ref T instance, object value) { SetValue(propertyInfo, ref instance, value, null); } /// /// Définit la valeur d'une propriété pour un objet. Equivalent à PropertyInfo.GetValue, /// mais fonctionne aussi pour les types valeur. /// /// Type de l'objet /// Descripteur de la propriété /// objet pour lequel on définit la valeur de la propriété /// Nouvelle valeur de la propriété /// Index pour la propriété indexée, ou null si la propriété n'est pas indexée public static void SetValue(this PropertyInfo propertyInfo, ref T instance, object value, object[] index) { object obj = instance; propertyInfo.SetValue(obj, value, index); instance = (T)obj; } #endregion #region FieldInfo extensions /// /// Définit la valeur d'un champ pour un objet. Equivalent à FieldInfo.GetValue, /// mais fonctionne aussi pour les types valeur. /// /// Type de l'objet /// Descripteur du champ /// objet pour lequel on définit la valeur du champ /// Nouvelle valeur du champ public static void SetValue(this FieldInfo fieldInfo, ref T instance, object value) { object obj = instance; fieldInfo.SetValue(obj, value); instance = (T)obj; } #endregion } }