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
}
}