fusion de deux objets en C#

j'ai un modèle D'objet MyObject avec diverses propriétés. A un moment, j'ai deux instances de ces Myobjects: instance A et instance B. j'aimerais 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 j'avais seulement 1 classe avec 3 Propriétés, pas de problème, je pourrais facilement la coder (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.

Qu'est-ce que une bonne façon de le faire?

24
demandé sur Anders Abel 2012-01-02 19:36:19

5 réponses

mise à Jour Utilisez AutoMapper à la place, si vous devez beaucoup invoquer cette méthode. Automapper construit des méthodes dynamiques en utilisant Reflection.Emit et sera beaucoup plus rapide que de réflexion.'

vous pouvez copier les valeurs des propriétés en utilisant reflection:

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 fait générique pour assurer la sécurité du type. Si vous souhaitez inclure les propriétés privées, vous devez utiliser un remplacement de Type.GetProperties (), spécifiant les drapeaux de liaison.

33
répondu Bas 2018-06-26 14:47:27

j'ai essayé fusionner deux objets dans un Type anonyme par Kyle Finley et c'est le travail parfait.

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 ça que vous avez obtenu l'objet fusionné, en dehors de cela, il y a une disposition à ignorer les propriétés spécifiques. Vous pouvez utiliser la même chose pour MVC3 aussi.

6
répondu Naveen Vijay 2017-05-07 08:25:23

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

puisque vous travaillez avec un design de classe attendu, vous pouvez atteindre le même objectif en utilisant une méthode d'extension comme so:

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;
             }
    }
}
someInstanceOfMyClass.Merge(someOtherInstanceOfMyClass);

à la fin de la journée vous avez centralisé cette opération dans une méthode d'extension et si vous ajoutez ou supprimez une propriété de votre classe, vous avez seulement besoin de modifier la méthode d'extension mise en œuvre et vous obtiendrez tout fait.

2
répondu Matías Fidemraizer 2012-01-02 15:47:05

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

Fondamentalement, il utilise des réflexions (et peut être lent à cause de cela). Il contient également plus de fonctionnalités, par exemple parsing objets pour les références cycliques et les fusionner aussi. Mon ObjectMerger contient également un mécanisme pour gérer des classes plus complexes comme Delegate ou MemberInfo. Ceux-ci seront copiés complètement, les autres objets de la classe sont fusionnés récursivement.

la Syntaxe est La suivante comme:

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 que ce n'est pas pour être utilisé tel quel, parce que certaines bibliothèques externes sont manquantes dans le dépôt en ce moment en raison de limitations dans mon entreprise, mais elles peuvent facilement être réécrites. J'espère pouvoir les ajouter à l'avenir.

0
répondu Markus Weber 2016-09-22 18:45:52

c'est la même réponse que @Bas mais pour la fusion de 2 objets listes

public class Copycontents
{
    public static void Work<T>(IList<T> targetList, IList<T> sourceList, Func<T, int> selector)
    {
        var matchingPrimaryKey = targetList.Select(x => selector(x)).ToList();

        foreach (var thismatchingPrimaryKey in matchingPrimaryKey)
        {
            CopyValues<T>(targetList.Single(x => selector(x) == thismatchingPrimaryKey),
                sourceList.Single(x => selector(x) == thismatchingPrimaryKey));
        }
    }

    private static 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);
        }
    }
}
0
répondu Yehia Amer 2017-05-07 08:25:37