Utilisation
|
Pour utiliser GetProperties avec des BindingFlags il faut obligatoirement spécifier BindingFlags.Instance ou BindingFlags.Static. |
|
// instanciation dynamique de MaClass
var maClass = (MaClass)Activator.CreateInstance(typeof(MaClass));
// récupération de la valeur du champs statique _staticField
// GetValue(null) doit être utilisé pour obtenir les valeurs des membres statiques
maClass.GetType().GetField("_staticField").GetValue(null);
// récupération de la valeur du champs privé _privateField
// par défaut les champs statiques ne sont pas recherchés, il faut utiliser les BindingFlags
maClass.GetType().GetField("_privateField", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(maClass);
// récupération de la valeur de la propriété PublicProperty
maClass.GetType().GetProperty("PublicProperty").GetValue(maClass, null);
// récupération des propriétés publiques en excluant celles des classes parentes (DeclaredOnly)
foreach (var propertyInfo in maClass.GetType().GetProperties(
BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly))
{ ... }
// exécute la méthode PublicMethod
maClass.GetType().GetMethod("PublicMethod").Invoke(maClass, new object[] { 10 }));
// savoir si un type à un constructeur par défaut
if (typeof(MaClass).GetConstructor(Type.EmptyTypes) != null) { }
class MaClass
{
private int _privateField;
public static int _staticField = 5;
public string PublicProperty { get; set; }
public int PublicMethod(int parameter)
{
return ++parameter;
}
public MaClass()
{
_privateField = 1;
}
}
|
Types générique
Ce code permet d'instancier un type générique depuis une méthode qui ne l'est pas.
|
// récupère le type GenericClass<int>
Type genericType = typeof(GenericClass<>).MakeGenericType(typeof(int));
// instancie le type, 10 est le paramètre passé au constructeur
var genericEvent = Activator.CreateInstance(genericType, 10);
// récupérer le type inclut dans la classe générique
var genericArguments = genericType.GetGenericArguments(); // tableau de types correspondant aux types <T1, T2, ...>
genericArguments[0]; // Int32
class GenericClass<T>
{
public int i { get; set; }
public GenericClass(int i) { this.i = i; }
}
|
Obtenir le nom d'une propriété au format String
|
// Méthode 1
// Réflexion sur la classe C1 :
ReflectionUtility.GetPropertyName(() => default(C1).P1);
// Réflexion sur l'objet c1 :
ReflectionUtility.GetPropertyName(() => cc1.P1)
// Méthode 2, réflexion sur la classe C1 sans la fausse erreur de compilation :
ReflectionUtility.GetPropertyName((C1 c1) => c1.P1);
// Méthode 3, extension :
c1.GetPropertyName(() => c1.P1);
public class C1
{
public int P1 { get; set; }
}
public static class ReflectionUtility
{
public static string GetPropertyName<T>(Expression<Func<T>> expression)
{
return ((MemberExpression)expression.Body).Member.Name;
}
public static string GetPropertyName<T, TReturn>(this Expression<Func<T, TReturn>> expression)
{
return ((MemberExpression)expression.Body).Member.Name;
}
public static string GetPropertyName<Tclass, Tproperty>(this Tclass obj, Expression<Func<Tproperty>> expression) where Tclass : class
{
return ((MemberExpression)expression.Body).Member.Name;
}
}
|
web site
|
// Ne marche pas
foreach (var prop in this.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty))
foreach (var prop in this.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
if (prop.GetSetMethod() != null)
|
Lister les classes, interfaces, enum d'une assembly
|
var systemAssembly = Assembly.GetAssembly(typeof(Console));
var allSystemTypes = systemAssembly.GetTypes().
Where(t => t.IsPublic && t.IsClass ||t.IsInterface || t.IsEnum).
OrderBy(t => t.Name).Select(t => t.Name);
File.AppendAllText("SystemTypes.txt", Regex.Replace(String.Join(" ", allSystemTypes), @"`\d", ""));
|
|
var mc = new MyClass();
var prop1 = mc.GetType().GetProperty("MyProperty1");
// code utilisant la réflexion
prop1.SetValue(mc, "test");
var v2 = prop1.GetValue(mc);
// code utilisant les Expression, bien plus rapide
var fp = new FastProperty(prop1);
fp.SetDelegate(mc, "test");
var v = fp.GetDelegate(mc);
class FastProperty
{
public PropertyInfo Property { get; set; }
public Func<object, object> GetDelegate;
public Action<object, object> SetDelegate;
public FastProperty(PropertyInfo property)
{
this.Property = property;
InitializeGet();
InitializeSet();
}
private void InitializeSet()
{
var instance = Expression.Parameter(typeof(object), "instance");
var value = Expression.Parameter(typeof(object), "value");
// value as T is slightly faster than (T)value, so if it's not a value type, use that
UnaryExpression instanceCast = (!this.Property.DeclaringType.IsValueType) ?
Expression.TypeAs(instance, this.Property.DeclaringType) :
Expression.Convert(instance, this.Property.DeclaringType);
UnaryExpression valueCast = (!this.Property.PropertyType.IsValueType) ?
Expression.TypeAs(value, this.Property.PropertyType) :
Expression.Convert(value, this.Property.PropertyType);
this.SetDelegate = Expression.Lambda<Action<object, object>>(
Expression.Call(
instanceCast,
this.Property.GetSetMethod(),
valueCast),
new ParameterExpression[] { instance, value }).Compile();
}
private void InitializeGet()
{
var instance = Expression.Parameter(typeof(object), "instance");
UnaryExpression instanceCast = (!this.Property.DeclaringType.IsValueType) ?
Expression.TypeAs(instance, this.Property.DeclaringType) :
Expression.Convert(instance, this.Property.DeclaringType);
this.GetDelegate = Expression.Lambda<Func<object, object>>(
Expression.TypeAs(
Expression.Call(instanceCast, this.Property.GetGetMethod()),
typeof(object)),
instance).Compile();
}
public object Get(object instance)
{
return this.GetDelegate(instance);
}
public void Set(object instance, object value)
{
this.SetDelegate(instance, value);
}
}
|