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

Utilisateur anonyme - 18 mai 2016 à 22:51 - Dernière réponse :  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
Afficher la suite 

Votre réponse

14 réponses

Whismeril 11617 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 17 juin 2018 Dernière intervention - 19 mai 2016 à 08:27
0
Merci
Bonjour ce que tu entends par sous classes, c'est une propriété dont le type a lui même des propriétés?
Commenter la réponse de Whismeril
Utilisateur anonyme - 19 mai 2016 à 09:57
0
Merci
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
Commenter la réponse de Utilisateur anonyme
Whismeril 11617 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 17 juin 2018 Dernière intervention - Modifié par Whismeril le 19/05/2016 à 12:09
0
Merci
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
Commenter la réponse de Whismeril
Utilisateur anonyme - 19 mai 2016 à 12:10
0
Merci
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...
Commenter la réponse de Utilisateur anonyme
Whismeril 11617 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 17 juin 2018 Dernière intervention - 19 mai 2016 à 20:19
0
Merci
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.
Whismeril 11617 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 17 juin 2018 Dernière intervention - 19 mai 2016 à 21:11
.
Commenter la réponse de Whismeril
Whismeril 11617 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 17 juin 2018 Dernière intervention - 19 mai 2016 à 21:12
0
Merci
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;
        }

Commenter la réponse de Whismeril
Utilisateur anonyme - 20 mai 2016 à 07:51
0
Merci
Merci !

Si on tombe dans le else c'est que forcement on est sur une classe perso ?
Whismeril 11617 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 17 juin 2018 Dernière intervention - 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.
Commenter la réponse de Utilisateur anonyme
Utilisateur anonyme - 20 mai 2016 à 08:11
0
Merci
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
Whismeril 11617 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 17 juin 2018 Dernière intervention - 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....
Utilisateur anonyme > Whismeril 11617 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 17 juin 2018 Dernière intervention - 20 mai 2016 à 08:30
Je pense faire cela comme ça alors
Je te remercie de ta précieuse aide
Commenter la réponse de Utilisateur anonyme
Utilisateur anonyme - 20 mai 2016 à 10:08
0
Merci
Penses tu que je puisse également récupérer le nom complet de la propriété ? Genre Customer.Quantity.Number ?

Merci
Commenter la réponse de Utilisateur anonyme
Utilisateur anonyme - 20 mai 2016 à 12:46
0
Merci
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
Commenter la réponse de Utilisateur anonyme

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.