C# Reflexion - Comparer propriétés sous classe

Utilisateur anonyme - Modifié par azertya255 le 18/05/2016 à 22:51
 Utilisateur anonyme - 20 mai 2016 à 12:46
Bonjour,

J'ai une méthode qui compare les propriétés de deux objets de même type :

public static void AreEquals(object objectA, object objectB)
{
 if (objectA != null && objectB != null)
 {
  Type objectType;

  objectType = objectA.GetType();

  foreach (PropertyInfo propertyInfo in objectType.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.CanRead))
  {
   object valueA = propertyInfo.GetValue(objectA, null);
   object valueB = propertyInfo.GetValue(objectB, null);

   if (typeof(IComparable).IsAssignableFrom(propertyInfo.PropertyType) || propertyInfo.PropertyType.IsPrimitive || propertyInfo.PropertyType.IsValueType)
   {
    if (!AreValuesEqual(valueA, valueB))
     Console.WriteLine(propertyInfo.Name + " not equal");
   }
   else
    Console.WriteLine(propertyInfo.Name + " not equal");
  }
 }
}

private static bool AreValuesEqual(object valueA, object valueB)
{
 bool result;

 IComparable selfValueComparer = valueA as IComparable;

 if (valueA == null && valueB != null || valueA != null && valueB == null)
  result = false;

 else if (selfValueComparer != null && selfValueComparer.CompareTo(valueB) != 0)
  result = false;

 else if (!object.Equals(valueA, valueB))
  result = false;

 else
  result = true;

 return result;
}


Mais cette methode ne compare pas les propriétés des sous classes.

Comment modifier cela pour entrer et comparer les propriétés des sous classes ?

Merci

10 réponses

Whismeril Messages postés 19024 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 18 avril 2024 656
19 mai 2016 à 08:27
Bonjour ce que tu entends par sous classes, c'est une propriété dont le type a lui même des propriétés?
0
Utilisateur anonyme
19 mai 2016 à 09:57
Oui comme les sous propriétés de la propriété Quantity dans cette exemple :

public class Customer
{
	public string FirstName { get; set; }
 
	public string LastName { get; set; }
 
	public Quantity Quantity { get; set; }
}
 
public class Quantity
{
	public string Color { get; set; }
 
	public int Number { get; set; }
}


Merci
0
Whismeril Messages postés 19024 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 18 avril 2024 656
Modifié par Whismeril le 19/05/2016 à 12:09
S'il ne s'agit que de classe que tu as écrite, tu peux te passer de la réflexion en écrivant l'opérateur == de chacune.
C'est un peu long à écrire, mais à l'exécution c'est plus rapide.

Par contre, si tu n'écrits que ==, tu auras un avertissement pour !=, equals et je ne sais plus lequel.
Pour !=, il suffit de retourner ! ==. Pour les 2 autres, tu retournes base.Equals et base.JeSaisPlus.

https://msdn.microsoft.com/fr-fr/library/aa288467(v=vs.71).aspx

Code tapé sans VS donc mef...

public class Customer
{
 public string FirstName { get; set; }
 
 public string LastName { get; set; }
 
 public Quantity Quantity { get; set; }

        public static bool operator ==(Customer Moi, Customer Autre)
        {
                  return (Moi.FirstName  == Autre.FirstName ) && (Moi.LastName == Autre.LastName ) && (Moi.Quantity == Autre.Quantity );
         }

}
 
public class Quantity
{
 public string Color { get; set; }
 
 public int Number { get; set; }

        public static bool operator ==(Quantity  Moi, Quantity Autre)
        {
                  return (Moi.Color == Autre.Color ) && (Moi.Number == Autre.Number );
         }

}


Je tacherais de regarder ton code avec reflexion en fin de journée.

Quand j'étais petit, la mer Morte n'était que malade.
George Burns
0
Utilisateur anonyme
19 mai 2016 à 12:10
Je te remercie de ta réponse

J'ai vraiment énormément de propriétés et je ne peux pas me permettre de faire cela comme ca...
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Whismeril Messages postés 19024 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 18 avril 2024 656
19 mai 2016 à 20:19
Bon déjà, j'ai un petit soucis, je me suis servit des classes de ta précédente question, en utilisant la dernière option que je t'ai proposé, à savoir une classe dérivée pour l'import.

Et bien le réflexion reconnait le type de la classe dérivée....
Donc, elle trouve la propriété qu'elle ne devrait pas voir, ça n'est pas un problème en soit pour ta question en cours mais peut-être pour la précédente.
0
Whismeril Messages postés 19024 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 18 avril 2024 656
Modifié par Whismeril le 19/05/2016 à 21:11
.
0
Whismeril Messages postés 19024 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 18 avril 2024 656
19 mai 2016 à 21:12
En faisant en sorte que AreEquals retourne un bool.

Quand on tombe sur une classe perso, on appelle de façon récursive la méthode
        public static bool AreEquals(object objectA, object objectB)
        {
            if (objectA != null && objectB != null)
            {
                Type objectType;

                objectType = objectA.GetType();

                foreach (PropertyInfo propertyInfo in objectType.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.CanRead))
                {
                    object valueA = propertyInfo.GetValue(objectA, null);
                    object valueB = propertyInfo.GetValue(objectB, null);

                    if (typeof(IComparable).IsAssignableFrom(propertyInfo.PropertyType) || propertyInfo.PropertyType.IsPrimitive || propertyInfo.PropertyType.IsValueType)
                    {
                        if (!AreValuesEqual(valueA, valueB))
                            return false;
                        //Console.WriteLine(propertyInfo.Name + " not equal");
                    }
                    else if (!AreEquals(valueA, valueB))
                        return false;
                        //Console.WriteLine(propertyInfo.Name + " not equal");
                }

                return true;
            }
            return false;//là il faudra voir ce que tu veux comme résultat si au moins un des 2 est null
        }

        private static bool AreValuesEqual(object valueA, object valueB)
        {
            bool result;

            IComparable selfValueComparer = valueA as IComparable;


            //Dans l'abosule ne sert à rien, puisque cette méthode est privée et que dans l'autre on commence par vérifier qu'aucun est null
            if (valueA == null && valueB != null || valueA != null && valueB == null)
                result = false;
                
            else if (selfValueComparer != null && selfValueComparer.CompareTo(valueB) != 0)
                result = false;

            else if (!object.Equals(valueA, valueB))
                result = false;

            else
                result = true;

            return result;
        }

0
Utilisateur anonyme
20 mai 2016 à 07:51
Merci !

Si on tombe dans le else c'est que forcement on est sur une classe perso ?
0
Whismeril Messages postés 19024 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 18 avril 2024 656
20 mai 2016 à 08:09
En tout ça n'est pas un type primitif, ni un type valeur (donc ça exclue les structures) ni un type qui est assignable par un IComparable, donc que tu as prévu pour.
0
Utilisateur anonyme
20 mai 2016 à 08:11
Il y a pas moyen de savoir via le propertyInfo de savoir si on est vraiment dans le cas d'une propriété perso ?

Merci encore
0
Whismeril Messages postés 19024 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 18 avril 2024 656
20 mai 2016 à 08:29
Tu peux te servir de typeof() mais il faudra que tu testes avec des if chacune de tes classes.
A priori ton code original était déjà bien pensé, perso je ne serai contenté de regarder si on est face un type primitif, car sinon c'est forcément un type construit....
0
Utilisateur anonyme > Whismeril Messages postés 19024 Date d'inscription mardi 11 mars 2003 Statut Contributeur Dernière intervention 18 avril 2024
20 mai 2016 à 08:30
Je pense faire cela comme ça alors
Je te remercie de ta précieuse aide
0
Utilisateur anonyme
20 mai 2016 à 10:08
Penses tu que je puisse également récupérer le nom complet de la propriété ? Genre Customer.Quantity.Number ?

Merci
0
Utilisateur anonyme
20 mai 2016 à 12:46
J'ai fait quelque chose comme ça qui fonctionne mais on a pas le nom complet depuis la base :

public static void AreEquals(object objectA, object objectB)
{
	if (objectA != null && objectB != null)
	{
		Type objectType;

		objectType = objectA.GetType();

		foreach (PropertyInfo propertyInfo in objectType.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(x => x.CanRead))
		{
			object valueA = propertyInfo.GetValue(objectA, null);
			object valueB = propertyInfo.GetValue(objectB, null);

			if (typeof(IComparable).IsAssignableFrom(propertyInfo.PropertyType) || propertyInfo.PropertyType.IsPrimitive || propertyInfo.PropertyType.IsValueType)
			{
				if (!AreValuesEqual(valueA, valueB))
					Console.WriteLine(propertyInfo.ReflectedType.Name + "." + propertyInfo.Name + " not equal");
			}
			else
			{
				AreEquals(valueA, valueB);
			}
		}
	}
}


Merci
0
Rejoignez-nous