it-swarm.com.de

Bewährte Methoden zum Zuordnen eines Objekts zu einem anderen

Meine Frage ist, wie ich ein Objekt auf die am besten zu wartende Weise einem anderen zuordnen kann. Ich kann die Art und Weise, wie das Dto-Objekt, das wir erhalten, normalisiert wird, nicht ändern, daher muss ich eine Möglichkeit erstellen, dies auf unsere Implementierung ihres Objekts abzubilden.

Hier ist ein Beispielcode, der zeigt, was ich tun muss:

class Program
{
    static void Main(string[] args)
    {
        var dto = new Dto();

        dto.Items = new object[] { 1.00m, true, "Three" };
        dto.ItemsNames = new[] { "One", "Two", "Three" };            

        var model = GetModel(dto);

        Console.WriteLine("One: {0}", model.One);
        Console.WriteLine("Two: {0}", model.Two);
        Console.WriteLine("Three: {0}", model.Three);
        Console.ReadLine();
    }

    private static Model GetModel(Dto dto)
    {
        var result = new Model();

        result.One = Convert.ToDecimal(dto.Items[Array.IndexOf(dto.ItemsNames, "One")]);
        result.Two = Convert.ToBoolean(dto.Items[Array.IndexOf(dto.ItemsNames, "Two")]);
        result.Three = dto.Items[Array.IndexOf(dto.ItemsNames, "Three")].ToString();

        return result;
    }
}

class Dto
{
    public object[] Items { get; set; }
    public string[] ItemsNames { get; set; }
}

class Model
{
    public decimal One { get; set; }
    public bool Two { get; set; }
    public string Three { get; set; }
}

Ich denke, was wäre toll, wenn ich eine Art Mapper-Klasse hätte, die die Modellobjekte propertyInfo, den Typ, in den ich konvertieren möchte, und den "itemname", den ich herausziehen möchte, aufnehmen würde. Hat jemand irgendwelche Vorschläge, um dieses sauberer zu machen?

Vielen Dank!

32
Alex

Ich würde mich für AutoMapper entscheiden, eine Open-Source- und freie Zuordnungsbibliothek, die es ermöglicht, einen Typ auf der Grundlage von Konventionen einem anderen zuzuordnen (dh öffentliche Eigenschaften mit demselben Namen und demselben/abgeleiteten/konvertierbaren Typ zuzuordnen) mit vielen anderen kluge ). Sehr einfach zu bedienen, können Sie so etwas erreichen:

Model model = Mapper.Map<Model>(dto);

Sie sind sich nicht sicher über Ihre spezifischen Anforderungen, aber AutoMapper unterstützt auch benutzerdefinierte Wertauflöser , was Ihnen beim Schreiben einer einzelnen generischen Implementierung Ihres speziellen Mapper helfen sollte.

22
Efran Cobisi

Dies ist eine mögliche generische Implementierung mit ein wenig Reflektion (Pseudocode, habe jetzt kein VS):

public class DtoMapper<DtoType>
{
    Dictionary<string,PropertyInfo> properties;

    public DtoMapper()
    {
        // Cache property infos
        var t = typeof(DtoType);
        properties = t.GetProperties().ToDictionary(p => p.Name, p => p);
     }

    public DtoType Map(Dto dto)
    {
        var instance = Activator.CreateInstance(typeOf(DtoType));

        foreach(var p in properties)
        {
            p.SetProperty(
                instance, 
                Convert.Type(
                    p.PropertyType, 
                    dto.Items[Array.IndexOf(dto.ItemsNames, p.Name)]);

            return instance;
        }
    }

Verwendung:

var mapper = new DtoMapper<Model>();
var modelInstance = mapper.Map(dto);

Dies ist langsam, wenn Sie die Mapper-Instanz erstellen, aber später viel schneller.

6
Stefano Altieri
/// <summary>
/// map properties
/// </summary>
/// <param name="sourceObj"></param>
/// <param name="targetObj"></param>
private void MapProp(object sourceObj, object targetObj)
{
    Type T1 = sourceObj.GetType();
    Type T2 = targetObj.GetType();

    PropertyInfo[] sourceProprties = T1.GetProperties(BindingFlags.Instance | BindingFlags.Public);
    PropertyInfo[] targetProprties = T2.GetProperties(BindingFlags.Instance | BindingFlags.Public);

   foreach (var sourceProp in sourceProprties)
   {
       object osourceVal = sourceProp.GetValue(sourceObj, null);
       int entIndex = Array.IndexOf(targetProprties, sourceProp);
       if (entIndex >= 0)
       {
           var targetProp = targetProprties[entIndex];
           targetProp.SetValue(targetObj, osourceVal);
       }
   }
}
3
DKM