2009-08-13 11 views
14

He estado trabajando con C# durante muchos años, pero me encuentro con este tema que me está abrumando, y realmente ni siquiera sé cómo hacer la pregunta, ¡así que, al ejemplo!copia de la propiedad de la interfaz en C#

public interface IAddress 
{ 
    string Address1 { get; set; } 
    string Address2 { get; set; } 
    string City { get; set; } 
    ... 
} 

public class Home : IAddress 
{ 
    // IAddress members 
} 

public class Work : IAddress 
{ 
    // IAddress members 
} 

Mi pregunta es, quiero copiar el valor de las propiedades de IAddress de una clase a otra. ¿Es esto posible en una simple declaración de una línea o aún tengo que hacer una asignación de propiedad a propiedad de cada uno? De hecho, estoy bastante sorprendido de que esta cosa aparentemente simple me haya dejado perplejo como lo ha hecho ... Si no es posible de una manera concisa, ¿alguien tiene algún atajo que use para hacer este tipo de cosas?

Gracias!

+0

Pensando que esto podría ser un duplicado de http://stackoverflow.com/questions/563253/c-generic-copy-constructor. si nada más, debería responder a su pregunta. –

Respuesta

2

No hay una sola línea para esto.

Si lo hace mucho, podría buscar en algún tipo de generación de código, tal vez utilizando plantillas T4 y Reflection.

BTW COBOL tiene una declaración para esto: MUEVA LA CASA CORRESPONDIENTE AL TRABAJO.

12

Se puede construir un método de extensión:

public static void CopyAddress(this IAddress source, IAddress destination) 
{ 
    if (source is null) throw new ArgumentNullException("source"); 
    if (destination is null) throw new ArgumentNullException("destination"); 

    //copy members: 
    destination.Address1 = source.Address1; 
    //... 
} 
+0

Me gusta mucho esta solución. ¡Gracias! – opedog

+2

Consulte la respuesta a continuación que tiene un método de extensión genérico que no es frágil cuando la interfaz cambia o los métodos set/get se agregan o eliminan. – plinth

1

lo que se necesita para crear un método para hacer esto

public void CopyFrom(IAddress source) 
{ 
    this.Address1 = source.Address1; 
    this.Address2 = source.Address2; 
    this.City = source.city; 
} 
+0

Este es un método frágil, es probable que se rompa si se agregan nuevas propiedades. – plinth

+0

Sí, la mayoría de las formas, excepto si usa el reflejo. Hacer lo que el usuario está hablando de esto es una opción válida. –

0

Usted podría tener un constructor en cada clase tomando un IAddress y tienen miembros implementadas poblado dentro.

por ejemplo

public WorkAddress(Iaddress address) 
{ 
    Line1 = IAddress.Line1; 
    ... 
} 

Para uso de mantenimiento de reflexión para obtener los nombres de propiedades.

HTH,

Dan

0

Si encapsular las partes comunes de la dirección de su casa y el trabajo en una clase separada que puede hacer su vida más fácil. Luego puede simplemente copiar a través de esa propiedad. Esto me parece mejor diseño.

Alternativamente, puede ser capaz de hackear juntos una solución con reflejo y atributos donde el valor de las propiedades en un objeto se copian a las propiedades correspondientes (y marcadas) en el otro. Por supuesto, esto tampoco será una solución de una línea, pero puede ser más rápido y más fácil de mantener que otros si tiene un gran conjunto de propiedades.

2

No creo que haya una solución lista para este idioma (todas las propiedades necesitarían tener getters y setters).

Puede crear Dirección como una clase abstracta, con un método de Copiar (Dirección).

Como alternativa, podría hacer que el hogar y el trabajo TENGAN una dirección I, y no extender uno. La copia sería inmediata.

4

Jimmy Bogard's AutoMapper es muy útil para ese tipo de operación de mapeo.

+0

Apache Commons tenía una biblioteca llamada "BeanUtils" que solía usar cuando desarrollé en Java. Lo que sugiere Martinho Fernandes parece ser la biblioteca .net correspondiente más cercana. –

18

Aquí hay una manera de hacerlo que no tiene nada que ver con las interfaces:

public static class ExtensionMethods 
{ 
    public static void CopyPropertiesTo<T>(this T source, T dest) 
    { 
     var plist = from prop in typeof(T).GetProperties() where prop.CanRead && prop.CanWrite select prop; 

     foreach (PropertyInfo prop in plist) 
     { 
      prop.SetValue(dest, prop.GetValue(source, null), null); 
     } 
    } 
} 

class Foo 
{ 
    public int Age { get; set; } 
    public float Weight { get; set; } 
    public string Name { get; set; } 
    public override string ToString() 
    { 
     return string.Format("Name {0}, Age {1}, Weight {2}", Name, Age, Weight); 
    } 
} 

static void Main(string[] args) 
{ 
    Foo a = new Foo(); 
    a.Age = 10; 
    a.Weight = 20.3f; 
    a.Name = "Ralph"; 
    Foo b = new Foo(); 
    a.CopyPropertiesTo<Foo>(b); 
    Console.WriteLine(b); 
} 

En su caso, si sólo quiere un conjunto de propiedades de la interfaz para copiar usted puede hacer esto:

((IAddress)home).CopyPropertiesTo<IAddress>(b); 
+1

Probablemente deberías poner una restricción allí, donde T: IAddress. Luego, también podría almacenar en caché la búsqueda de Reflection en lugar de hacerlo para cada llamada y aún así evitar la necesidad de actualizar el método si la interfaz cambia. –

+0

Por cierto, entiendo que lo estás intentando para el caso más general, pero en este caso parece tratar de usar un martillo para golpear un clavo. –

+1

Su código se interrumpirá en el tiempo de ejecución si 'source' y' dest' son tipos diferentes, que están en la pregunta original. Puede solucionarlo obteniendo la lista de propiedades de 'T' en lugar de' fuente'. Por ejemplo: 'var plist = from prop en typeof (T) .GetProperties() donde prop.CanRead && prop.CanWrite select prop;' – LukeH

Cuestiones relacionadas