c# reflection shallow-copy

c# - ¿Cómo mejorarías esta clase de copia superficial?



reflection shallow-copy (4)

Escribí una clase con un único método estático que copia los valores de las propiedades de un objeto a otro. No importa qué tipo sea cada objeto, solo que tienen propiedades idénticas. Hace lo que necesito, así que no lo estoy diseñando más, pero ¿qué mejoras harías?

Aquí está el código:

public class ShallowCopy { public static void Copy<From, To>(From from, To to) where To : class where From : class { Type toType = to.GetType(); foreach (var propertyInfo in from.GetType().GetProperties(BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance)) { toType.GetProperty(propertyInfo.Name).SetValue(to, propertyInfo.GetValue(from, null), null); } } }

Lo estoy usando de la siguiente manera:

EmployeeDTO dto = GetEmployeeDTO(); Employee employee = new Employee(); ShallowCopy.Copy(dto, employee);


Decida qué quiere hacer si se pasan objetos de tipos que comparten algunas propiedades pero no todas. Verifique la existencia de la propiedad en el objeto From en el objeto To antes de intentar establecer su valor. Haga lo "correcto" cuando llegue a una propiedad que no existe. Si todas las propiedades públicas deben ser idénticas, deberá verificar si las ha configurado todas en el objeto To y manejar el caso en el que no lo haya hecho correctamente.

También sugiero que desee utilizar atributos para decorar las propiedades que deben copiarse e ignorar otras. Esto le permitiría ir y venir entre los dos objetos diferentes más fácilmente y continuar manteniendo algunas propiedades públicas derivadas en lugar de almacenadas en su objeto comercial.


Un nuevo método que creó una nueva instancia de To y llamó al método Copy() antes de regresar podría ser útil.

Me gusta esto:

public static To Create<From, To>(From from) where To : class, new() where From : class { var to = new To(); Copy(from, to); return to; }


  • Cambie los nombres de los parámetros de tipo para cumplir con las convenciones de denominación, por ejemplo, TFrom y TTo, o TSource y TDest (o TDestination).

  • Realice la mayor parte de su trabajo en un tipo genérico en lugar de simplemente en un método genérico. Eso le permite almacenar en caché las propiedades, así como también permitir la inferencia de tipo. La inferencia de tipo es importante en el parámetro "TFrom", ya que permitirá el uso de tipos anónimos.

  • Es posible que sea potencialmente deslumbrante al generar dinámicamente código para copiar la propiedad y mantenerla en un delegado que sea válido para el tipo "de". O potencialmente generarlo para cada par de / a, lo que significaría que la copia real no necesitaría usar ningún tipo de reflejo. (La preparación del código sería un golpe por única vez por par de tipos, pero es de esperar que no tenga demasiados pares).


¿Sus DTO son serializables? Yo esperaría eso, en cuyo caso:

MemberInfo[] sm = FormatterServices.GetSerializableMembers(typeof(From)); object[] data = FormatterServices.GetObjectData(from, sm); FormatterServices.PopulateObjectMembers(to, sm, data);

Pero tenga en cuenta que realmente no estoy de acuerdo con este enfoque general. Preferiría un contrato fuerte para copiar en sus DTO que implemente cada DTO.