68 votes

fusionner deux objets en C#

J'ai un modèle d'objet MyObject avec diverses propriétés. À un moment donné, j'ai deux instances de ce MyObject : l'instance A et l'instance B. Je voudrais copier et remplacer les propriétés de l'instance A par celles de l'instance B si l'instance B a des valeurs non nulles.

Si je n'avais qu'une seule classe avec 3 propriétés, pas de problème, je pourrais facilement la coder en dur (c'est ce que j'ai commencé à faire). Mais j'ai en fait 12 modèles d'objets différents avec environ 10 propriétés chacun.

Quelle est la bonne façon de procéder ?

82voto

Bas Brekelmans Points 13799

Mise à jour Utilisez AutoMapper à la place si vous devez invoquer cette méthode fréquemment. Automapper construit des méthodes dynamiques en utilisant Reflection.Emit et sera beaucoup plus rapide que la réflexion.

Vous pouvez copier les valeurs des propriétés en utilisant la réflexion :

public void CopyValues<T>(T target, T source)
{
    Type t = typeof(T);

    var properties = t.GetProperties().Where(prop => prop.CanRead && prop.CanWrite);

    foreach (var prop in properties)
    {
        var value = prop.GetValue(source, null);
        if (value != null)
             prop.SetValue(target, value, null);
    }
}

Je l'ai rendu générique pour assurer la sécurité des types. Si vous voulez inclure des propriétés privées, vous devez utiliser une surcharge de Type.GetProperties() en spécifiant les drapeaux de liaison.

15voto

Naveen Points 2480

J'ai essayé Fusionner deux objets en un type anonyme par Kyle Finley et il fonctionne parfaitement.

Avec le TypeMerger la fusion est aussi simple que

var obj1 = new {foo = "foo"};

var obj2 = new {bar = "bar"};

var mergedObject = TypeMerger.MergeTypes(obj1 , obj2 );

C'est ainsi que vous avez obtenu l'objet fusionné, à part cela, il y a une disposition pour ignorer des propriétés spécifiques aussi. Vous pouvez utiliser la même chose pour MVC3 aussi.

3voto

Matías Fidemraizer Points 16842

Vous pouvez le faire en utilisant la réflexion, mais comme quelqu'un l'a dit, cela aura une pénalité de performance.

Puisque vous travaillez avec une conception de classe attendue, vous pouvez atteindre le même objectif en utilisant une méthode d'extension comme suit :

public static class MyClassExtensions
{
    public static void Merge(this MyClass instanceA, MyClass instanceB)
    {
        if(instanceA != null && instanceB != null)
        {
             if(instanceB.Prop1 != null) 
             {
                 instanceA.Prop1 = instanceB.Prop1;
             }

             if(instanceB.PropN != null) 
             {
                 instanceA.PropN = instanceB.PropN;
             }
    }
}

Et plus tard, quelque part dans votre code :

someInstanceOfMyClass.Merge(someOtherInstanceOfMyClass);

Au final, vous avez centralisé cette opération dans une méthode d'extension et si vous ajoutez ou supprimez une propriété de votre classe, il vous suffit de modifier l'implémentation de la méthode d'extension et vous aurez tout fait.

1voto

Markus Weber Points 346

J'ai écrit ma propre classe dans ce but : ObjectMerger .

En fait, il utilise des réflexions (et peut être lent à cause de cela). Il contient également d'autres fonctionnalités, par exemple l'analyse des objets pour détecter les références cycliques et les fusionner également. Mon ObjectMerger contient également un mécanisme permettant de gérer des classes plus complexes telles que Delegate o MemberInfo . Ceux-ci seront copiés complètement, les autres objets de la classe sont fusionnés récursivement.

La syntaxe est la suivante :

var initialInstance = new MyObjectBase(); // Initialize first object
var properInstance = new MyObjectWithAlgorithms(); // Initialize second object
var result = ObjectMerger.MergeObjects(properInstance, initialInstance); // Merge Objects into type of "properInstance"

Je suis désolé de dire qu'il n'est pas à utiliser tel quel, car certaines bibliothèques externes sont manquantes dans le dépôt pour le moment en raison de limitations dans mon entreprise, mais elles peuvent facilement être réécrites. J'espère pouvoir les ajouter à l'avenir.

1voto

AlexXie Points 11

Vous pouvez utiliser ce paquet : XASoft

utiliser la méthode foo.Merger(bar) pour combiner 2 objets en un objet dynamique

juste comme ça

var objA = new { a = 1, b = 2, c = 3 };
var newObj = objA.Merger(new { a = "Hey", d = 4, e = 5 });
newObj.e = "There";
newObj.f = 6;
Console.WriteLine(JsonConvert.SerializeObject(newObj));

même si la liste d'objets fonctionne bien aussi !

private class TestClass
{
    public int X { get; set; }
    public int Y { get; set; }
}
static void Main(string[] args)
{
    var list = new List<TestClass> {
        new TestClass{ X=1,Y=2},
        new TestClass{ X=3,Y=4}
    };
    Console.WriteLine(JsonConvert.SerializeObject(list.ListMerger(i => new
        { X = "null value", Z = i.X == 1 ? 0 : 1 })));
}

oops, on dirait du langage javascript...

Au fait, le code source se trouve ici

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X