2012-01-23 6 views
10

Suponga que tiene 2 clases de este modo:¿Hay algo incorporado en .NET/C# para copiar valores entre objetos?

public class ClassA { 
    public int X { get; set; } 
    public int Y { get; set; } 
    public int Other { get; set; } 
} 

public class ClassB { 
    public int X { get; set; } 
    public int Y { get; set; } 
    public int Nope { get; set; } 
} 

Ahora imagine que tiene una instancia de cada clase y que desea copiar los valores de a en b. ¿Hay algo así como MemberwiseClone que copie los valores en los que coinciden los nombres de las propiedades (y, por supuesto, es tolerante a errores, uno tiene un get y el otro un set, etc.)?

var a = new ClassA(); var b = new classB(); 
a.CopyTo(b); // ?? 

Algo como esto es bastante fácil en un lenguaje como JavaScript.

Supongo que la respuesta es no, pero tal vez también hay una alternativa simple. He escrito una biblioteca de reflexión para hacer esto, pero si está integrado en C# /. NET en un nivel inferior, probablemente sería más eficiente (y por qué reinventar la rueda).

+2

eche un vistazo a AutoMapper: http://lostechies.com/jimmybogard/2009/01/23/automapper-the-object-object-mapper/ –

Respuesta

10

No hay nada en el marco para el mapeo objeto-objeto, pero hay una biblioteca muy popular que hace esto: AutoMapper.

AutoMapper es un poco simple biblioteca construida para resolver un problema complejo engañosamente - deshacerse de código que asigna un objeto a otro . Este tipo de código es bastante triste y aburrido para escribir, así que ¿por qué no inventar una herramienta para hacerlo por nosotros?

Por cierto, sólo para aprender, aquí está una manera sencilla se puede poner en práctica lo que quiere. No he probado a fondo, y es en ninguna parte tan robusta/flexibles/performant como AutoMapper, pero esperemos que hay algo para salir de la idea general:

public void CopyTo(this object source, object target) 
{ 
    // Argument-checking here... 

    // Collect compatible properties and source values 
    var tuples = from sourceProperty in source.GetType().GetProperties() 
       join targetProperty in target.GetType().GetProperties() 
            on sourceProperty.Name 
            equals targetProperty.Name 

       // Exclude indexers 
       where !sourceProperty.GetIndexParameters().Any() 
        && !targetProperty.GetIndexParameters().Any() 

       // Must be able to read from source and write to target. 
       where sourceProperty.CanRead && targetProperty.CanWrite 

       // Property types must be compatible. 
       where targetProperty.PropertyType 
            .IsAssignableFrom(sourceProperty.PropertyType) 

       select new 
       { 
        Value = sourceProperty.GetValue(source, null), 
        Property = targetProperty 
       }; 

    // Copy values over to target. 
    foreach (var valuePropertyTuple in tuples) 
    { 
     valuePropertyTuple.Property 
          .SetValue(target, valuePropertyTuple.Value, null); 

    } 
} 
-1

Por lo que yo sé que esto no existe. La forma en que he estado haciendo es por:

public static T DeepCopy(T oldclass) 
{ 
    using (MemoryStream stream = new MemoryStream()) 
    { 
     BinaryFormatter formatter = new BinaryFormatter(); 
     formatter.Serialize(stream, oldclass); 
     ms.Position = 0; 
     return (T)formatter.Deserialize(stream); 
    } 
} 
1

No hay nada como esto en .NET que yo sepa, pero una biblioteca que es capaz de hacer esto (y mucho más) es AutoMapper. Para su caso, algo así como:

_mapper.Map<A, B> (a, b); 
-1

Ver la interfaz System.ICloneable, y el método System.Object.MemberwiseClone(). Como se indica en los documentos de MSDN,

El método MemberwiseClone crea una copia superficial creando un nuevo objeto y luego copiando los campos no estáticos del objeto actual en el nuevo objeto. Si un campo es un tipo de valor, se realiza una copia bit por bit del campo. Si un campo es un tipo de referencia, la referencia se copia pero el objeto referido no; por lo tanto, el objeto original y su clon se refieren al mismo objeto.
+0

¿Así que usted dice que esto funcionaría? 'classB = classA.MemberwiseClone() como classB' –

Cuestiones relacionadas