2010-09-12 3 views
3

Je cherche un moyen de prendre deux objets qui ont des propriétés identiques et de faire un appel pour copier les valeurs de propriété d'un objet dans l'autre. Le l'exemple ci-dessous supposent que j'ai une instance de A et je veux utiliser les données de cette instance pour hydrater une nouvelle instance ou C (pour garder les choses laconique je champs au lieu de propriétés dans l'exemple ci-dessous)Comment copier des données de différentes classes en faisant correspondre des noms de champs ou de propriétés

public class A : B 
{ 
    public string prop1; 
    public int prop2; 
} 

public class B 
{ 
    public byte propX; 
    public float propY; 
} 

public class C 
{ 
    public byte propX; 
    public float propY; 
    public string prop1; 
    public int prop2; 
} 

public class Merger 
{ 
    public static object Merge(object copyFrom, object copyTo) 
    { 
     //do some work 
     //maybe <T> generically refactor? 
    } 
} 

La classe de fusion est juste un pseudo-exemple, faire cela par des génériques serait optimal mais la première chose que je demande est de savoir si une telle capacité existe déjà. Je pourrais imaginer utiliser la réflexion pour le faire moi-même, mais je voulais juste le jeter pour de meilleures idées d'abord.

Contexte réel: C'est en fait un problème lié à MVVM car j'essaie d'utiliser des classes disparates revenant de EF pour remplir une instance de ViewModel.

Répondre

8

Découvrez les outils et les bibliothèques comme AutoMapper - ceux qui traiteraient des cas comme celui-ci avec facilité - et bien plus encore! Pas besoin de réinventer la roue - utilisez simplement l'outil! :-)

Vous définiriez essentiellement une carte entre les classes A et C comme ceci:

Mapper.CreateMap<A, C>(); 

, puis plus tard, vous pouvez avoir AutoMapper faire la cartographie, en fonction de cette carte, d'une instance de a en une instance de C, quelque chose comme ceci:

C yourC = Mapper.Map<A, C>(instanceOfA); 

AutoMapper fait un mappage par défaut en fonction des noms de propriété (et types), mais vous pouvez étendre et d'influencer dans un grand nombre de façons d'inclure les correspondances d'une propriété à un autre, même si les noms (ou types) ne correspondent pas à 100%. C'est assez flexible et bien établi - ça vaut vraiment le coup d'oeil sérieux!

+0

Сool! C'est une très bonne chose –

1
using System; 
using System.Linq; 
using System.Reflection; 

public class Merger 
{ 
    public static TTarget Merge<TTarget>(object copyFrom) where TTarget : new() 
    { 
     var flags = BindingFlags.Instance | BindingFlags.Public | 
        BindingFlags.NonPublic; 
     var targetDic = typeof(TTarget).GetFields(flags) 
             .ToDictionary(f => f.Name); 
     var ret = new TTarget(); 
     foreach (var f in copyFrom.GetType().GetFields(flags)) 
     { 
      if (targetDic.ContainsKey(f.Name)) 
       targetDic[f.Name].SetValue(ret, f.GetValue(copyFrom)); 
      else 
       throw new InvalidOperationException(string.Format(
        "The field “{0}” has no corresponding field in the type “{1}”.", 
        f.Name, typeof(TTarget).FullName)); 
     } 
     return ret; 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var a = new A { prop1 = "one", prop2 = 2, propX = 127, propY = 0.47f }; 
     var c = Merger.Merge<C>(a); 
     Console.WriteLine(c.prop1); // prints one 
     Console.WriteLine(c.prop2); // prints 2 
     Console.WriteLine(c.propX); // prints 127 
     Console.WriteLine(c.propY); // prints 0.47 
    } 
} 
0

Ce n'est pas la meilleure solution de loin, mais basée sur le graphique d'objets que vous avez fourni, vous pouvez probablement accomplir cela en XML sérialisation le premier objet et XML désérialiser le flux XML dans le second objet .

Votre méthode Merger proposée pourrait ressembler à ceci:

public class Merger 
{ 
    public static object Merge(object copyFrom, object copyTo) 
    { 
     var xmlContent = MyXMLSerializationMethod(copyFrom); 
     MyXMLDeserializationMethod(xmlContent, typeof(copyTo), out copyTo); 
     return copyTo; 
    } 
} 
Questions connexes