Necesito realizar una clonación profunda en mi modelo de objeto complejo. ¿Cuál crees que es la mejor manera de hacerlo en .Net?
Pensé en serializar/deserializar
sin necesidad de mencionar que MemberwiseClone
no es suficiente..Net Deep cloning: ¿cuál es la mejor manera de hacerlo?
Respuesta
La mejor manera es probablemente implementar la interfaz System.IClonable en su objeto y todos sus campos que también necesitan capacidades personalizadas de clonación profunda. Luego implementa el método Clone para devolver una copia profunda de su objeto y sus miembros.
Todavía hay recomendaciones en contra de esto, y Estoy de acuerdo con ellas.Lo razonable en un objeto puede significar profundo, mientras que en otro es superficial. No hay forma de discernir cuando se realiza una llamada. Por supuesto, esto no es completamente aplicable a un proyecto interno, pero no es una mala práctica reconocer temprano. – jfsk3
IClonable no funciona para objetos complejos. –
Si controla el modelo de objetos, puede escribir el código para hacerlo, pero es mucho mantenimiento. Sin embargo, hay muchos problemas, lo que significa que, a menos que necesite absolutamente el rendimiento más rápido, la serialización suele ser la respuesta más manejable.
Este es uno de los casos en que BinaryFormatter
funciona aceptablemente; normalmente no soy seguidor (debido a problemas con el control de versiones, etc.), pero dado que los datos serializados son de consumo inmediato, esto no es un problema.
Si lo desea un poco más rápido (pero sin su propio código), entonces protobuf-net
puede ayudar, pero requiere cambios de código (para agregar los metadatos necesarios, etc.). Y está basado en un árbol (no basado en gráficos).
Otros serializadores (XmlSerializer
, DataContractSerializer
) también están muy bien, pero si es simplemente para el clon, es posible que no ofrecen mucho más BinaryFormatter
(excepto, quizás, que no necesita XmlSerializer
[Serializable]
.
Así que en realidad, que depende de sus clases exactas y el escenario.
Quizás un enlace al ejemplo sea agradable. Estoy usando UWP y no puedo usar BinaryFormatter. El serializador XML está dado a continuación por Marty. Tengo curiosidad sobre DataContractSerializer y protobuf-net. –
usted podría intentar AltSerialize que en muchos casos es más rápido que el serializador .Net. también proporciona almacenamiento en caché y atributos personalizados para acelerar la serialización.
Ejemplo de clonación profunda de la revista MSDN:
Object DeepClone(Object original)
{
// Construct a temporary memory stream
MemoryStream stream = new MemoryStream();
// Construct a serialization formatter that does all the hard work
BinaryFormatter formatter = new BinaryFormatter();
// This line is explained in the "Streaming Contexts" section
formatter.Context = new StreamingContext(StreamingContextStates.Clone);
// Serialize the object graph into the memory stream
formatter.Serialize(stream, original);
// Seek back to the start of the memory stream before deserializing
stream.Position = 0;
// Deserialize the graph into a new set of objects
// and return the root of the graph (deep copy) to the caller
return (formatter.Deserialize(stream));
}
Si está ejecutando código en un entorno de confianza parcial, como la nube de Rackspace es probable que se restringe el uso de la BinaryFormatter. El XmlSerializer se puede usar en su lugar.
public static T DeepClone<T>(T obj)
{
using (var ms = new MemoryStream())
{
XmlSerializer xs = new XmlSerializer(typeof(T));
xs.Serialize(ms, obj);
ms.Position = 0;
return (T)xs.Deserialize(ms);
}
}
No funciona cuando algunas propiedades del objeto clonado son interfaces (por ejemplo, IEnumerable, IList, etc.). Lanza una excepción. –
Por favor, eche un vistazo al muy buen artículo C# Object Clone Wars. Encontré una solución muy interesante allí: Copyable: A framework for copying or cloning .NET objects
La mejor manera de implementar esto manualmente. Será realmente más rápido que cualquier otro método genérico. Además, hay muchas bibliotecas para esta operación (Puede ver una lista con los parámetros de rendimiento here).
Por cierto, BinaryFormatter es muy lento para esta tarea y puede ser bueno solo para las pruebas.
- 1. Pregunta de diseño - java - ¿cuál es la mejor manera de hacerlo?
- 2. ¿Cuál es la mejor manera de consumir servicios web REST?
- 3. Twisted + SQLAlchemy y la mejor manera de hacerlo
- 4. La mejor manera de hacerlo: no en jQuery?
- 5. ¿Cuál es la mejor manera de mantener vivo el control de socket en .NET?
- 6. Cuál es la mejor manera de paginar resultados en php
- 7. ¿Cuál es la mejor manera de comenzar a utilizar MAPI?
- 8. ¿Cuál es la mejor manera de comparar programas en Windows?
- 9. Cuál es la mejor manera de actualizar entidades en nhibernate
- 10. ¿Cuál es la mejor manera de reutilizar el analizador Lua?
- 11. ¿Cuál es la mejor manera de depurar css en ie?
- 12. ¿Cuál es la mejor manera de ampliar la funcionalidad?
- 13. ¿Cuál es la mejor manera de solucionar problemas de rendimiento?
- 14. ¿Cuál es la mejor manera de diferir Crystal Reports?
- 15. ¿Cuál es la mejor manera de comenzar a usar Asterisk?
- 16. Cuál es la mejor manera de obtener la impresora predeterminada en .NET
- 17. Temporizadores .NET: ¿Cuál es la mejor manera de recibir notificaciones en X segundos?
- 18. ¿Cuál es la mejor manera de afirmar la igualdad numpy.array?
- 19. ¿Cuál es la mejor manera de dibujar en la consola?
- 20. ¿Cuál es la mejor manera de usar mongoDB con node.js?
- 21. ¿Cuál es la mejor manera de almacenar cadena de conexión en DLL de .NET?
- 22. ¿Cuál es la mejor manera de analizar una gramática simple?
- 23. ¿Cuál es la mejor manera de configurar una descripción del servicio de Windows en .net
- 24. ¿Cuál es la mejor manera de analizar los números localizados de .NET/Razor en javascript?
- 25. .NET: ¿Cuál es la mejor manera de implementar un controlador de excepciones "catch all"
- 26. ¿Cuál es la mejor manera de calcular el tamaño de un directorio en VB .NET?
- 27. ¿Cuál es la mejor manera de manejar objects.get de Django?
- 28. ¿Cuál es la mejor manera de alternar impresiones de pitón?
- 29. ¿Cuál es la mejor manera de almacenar datos de tendencia?
- 30. ¿Cuál es la mejor alternativa a int.TryParse para .net 1.1
Tenga mucho cuidado; ¿Es esto lo que realmente quieres decir? Las referencias circulares entre objetos pueden causar problemas rápidamente con la clonación profunda. –
esto lo hace sin serialización http://valueinjecter.codeplex.com/wikipage?title=Deep%20Cloning&referringTitle=Home – Omu
UltraMapper https://www.nuget.org/packages/UltraMapper/ – sam