Il y a au moins deux façons de le faire:
1.Reflection et PropertyInfo
var obj = new TestClass();
var allProps = typeof(TestClass).GetProperties();
foreach (var prop in allProps)
{
// Get propertie value
object propValue = prop.GetGetMethod().Invoke(obj, null);
//Set propertie value
prop.GetSetMethod().Invoke(obj, new object[] { propValue });
}
Vous devez être prudent en ce qui concerne la performance si, à rude épreuve pour une classe avec deux propriétés de réglage et d'obtenir toutes les propriétés 10k fois prend 0,06 secondes avec réflexion et 0,001 secondes si je l'écris à la main. Donc la performance est assez drastique
2.Dynamic Methods Cette méthode est plus compliquée mais les performances en valent la peine. Les méthodes dynamiques sont des méthodes pour lesquelles le programme émet MSIL lors de l'exécution. Ils sont exécutés par le runtime comme s'ils avaient été créés par le compilateur (donc la vitesse est très bonne). L'utilisation de cette méthode et l'obtention de 2 propriétés sur une classe de 10k fois prenaient 0,004 secondes (comparé à 0,06 secondes avec réflexion et 0,001 seconde à la main). Bellow est le code pour générer un tableau de délégués pour les getters et setters pour un certain type. Générer la dynamique peut être coûteux, donc vous devriez mettre en cache les délégués si vous avez l'intention d'utiliser plusieurs fois (ce qui sera probablement le cas).
//Container for getters and setters of a property
public class MyProp
{
public string PropName { get; set; }
public Func<object,object> Getter{get;set;}
public Action<object,object> Setter{get;set;}
}
public static MyProp[] CreatePropertyDelagates (Type type)
{
var allProps = type.GetProperties();
var props = new MyProp[allProps.Length];
for(int i =0;i<allProps.Length;i++)
{
var prop = allProps[i];
// Getter dynamic method the signature would be :
// object Get(object thisReference)
// { return ((TestClass)thisReference).Prop; }
DynamicMethod dmGet = new DynamicMethod("Get", typeof(object), new Type[] { typeof(object), });
ILGenerator ilGet = dmGet.GetILGenerator();
// Load first argument to the stack
ilGet.Emit(OpCodes.Ldarg_0);
// Cast the object on the stack to the apropriate type
ilGet.Emit(OpCodes.Castclass, type);
// Call the getter method passing the object on the stack as the this reference
ilGet.Emit(OpCodes.Callvirt, prop.GetGetMethod());
// If the property type is a value type (int/DateTime/..) box the value so we can return it
if (prop.PropertyType.IsValueType)
{
ilGet.Emit(OpCodes.Box, prop.PropertyType);
}
// Return from the method
ilGet.Emit(OpCodes.Ret);
// Setter dynamic method the signature would be :
// object Set(object thisReference, object propValue)
// { return ((TestClass)thisReference).Prop = (PropType)propValue; }
DynamicMethod dmSet = new DynamicMethod("Set", typeof(void), new Type[] { typeof(object), typeof(object) });
ILGenerator ilSet = dmSet.GetILGenerator();
// Load first argument to the stack and cast it
ilSet.Emit(OpCodes.Ldarg_0);
ilSet.Emit(OpCodes.Castclass, type);
// Load secons argument to the stack and cast it or unbox it
ilSet.Emit(OpCodes.Ldarg_1);
if (prop.PropertyType.IsValueType)
{
ilSet.Emit(OpCodes.Unbox_Any,prop.PropertyType);
}
else
{
ilSet.Emit(OpCodes.Castclass, prop.PropertyType);
}
// Call Setter method and return
ilSet.Emit(OpCodes.Callvirt, prop.GetSetMethod());
ilSet.Emit(OpCodes.Ret);
// Create the delegates for invoking the dynamic methods and add the to an array for later use
props[i] = new MyProp()
{
PropName = prop.Name,
Setter = (Action<object, object>)dmSet.CreateDelegate(typeof(Action<object, object>)),
Getter = (Func<object, object>)dmGet.CreateDelegate(typeof(Func<object, object>)),
};
}
return props;
}
des méthodes Invocation dynamiques:
// Should be cahced for further use
var testClassProps = CreatePropertyDelagates(typeof(TestClass));
var obj = new TestClass();
foreach (var p in testClassProps)
{
var propValue = p.Getter(obj);
p.Setter(obj,propValue);
}
Obs: Le code ci-dessus traite pas avec des propriétés qui n'ont pas getter ou pas setter ou sont privées. Cela pourrait être facilement fait en regardant les propriétés de la classe ProperyInfo et en ne créant que les délégués si cela est approprié.
La réflexion ne serait-elle pas meilleure? –
Je ne sais pas ce que vous cherchez ici. Au lieu de la solution proposée, pourriez-vous expliquer le problème que vous essayez de résoudre? –
Sont-ils tous du même type? Si c'est le cas, un Dictionary pourrait convenir. –
AakashM