2016-05-12 17 views
2

Ich habe eine große Klasse mit vielen Eigenschaften (BigClass). Ich muss eine neue Klasse (SmallClass) mit nur einigen dieser Eigenschaften erstellen. Diese SmallClass muss alle überlappenden Eigenschaften von BigClass verwenden. Was ist der einfachste Weg, dies zu tun, ohne manuell alle Eigenschaften im Konstruktor von SmallClass zuweisen wie ich weiter unten tun:Kopieren Sie einige Eigenschaften in neue Konstruktor

class BigClass 
{ 
    public int A { get; } 
    public int B { get; } 
    public int C { get; } 
    public int D { get; } 
    public int E { get; } 

    public BigClass(int a, int b, int c, int d, int e) 
    { 
     A = a; 
     B = b; 
     C = c; 
     D = d; 
     E = e; 
    } 
} 

class SmallClass 
{ 
    public int A { get; } 
    public int B { get; } 
    public int C { get; } 

    public SmallClass(BigClass bigClass) 
    { 
     // I don't want to do all this manually: 
     A = bigClass.A; 
     B = bigClass.B; 
     C = bigClass.C; 
    } 
} 
+3

Müssen Sie es überhaupt tun? Könnte 'BigClass' zum Beispiel von' SmallClass' erben? Wenn nicht, und Sie tun es mit einer Schleife mit Reflektion usw., was würde auf lange Sicht passieren, wenn sowohl "BigClass" als auch "SmallClass" versehentlich den gleichen Eigenschaftennamen, aber für völlig unabhängige Zwecke verwendet werden? –

+2

Bitte schauen Sie auf http://automapper.org/ – Lucian

+0

Ich bin ein Fan von AutoMapper sowie –

Antwort

0

erstellen Hilfsklasse:

public class Helper 
{ 
    public static void CopyItem<T>(BigClass source, T target) 
    { 
     // Need a way to rename the backing-field name to the property Name ("<A>k__BackingField" => "A") 
     Func<string, string> renameBackingField = key => new string(key.Skip(1).Take(key.IndexOf('>') - 1).ToArray()); 

     // Get public source properties (change BindingFlags if you need to copy private memebers as well) 
     var sourceProperties = source.GetType().GetProperties().ToDictionary(item => item.Name); 
     // Get "missing" property setter's backing field 
     var targetFields = typeof(T).GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetField).ToDictionary(item => renameBackingField(item.Name)); 

     // Copy properties where target name matches the source property name 
     foreach(var sourceProperty in sourceProperties) 
     { 
      if (targetFields.ContainsKey(sourceProperty.Key) == false) 
       continue; // No match. skip 

      var sourceValue = sourceProperty.Value.GetValue(source); 
      targetFields[sourceProperty.Key].SetValue(target, sourceValue); 
     } 
    } 
} 

Dann in Ihrem Kleinen Konstruktor :

public SmallClass(BigClass bigClass) 
{ 
    Helper.CopyItem(bigClass, this); 
} 

Dies sollte funktionieren, auch wenn Sie nur Eigenschaften getters haben.

Sie können CopyItem mit allen Typen arbeiten lassen, indem Sie seine Deklaration ändern;

public static void CopyItem<U, T>(U source, T target) 
Verwandte Themen