Whilst the standard practice is to implement the ICloneable
interface (described here , so I won't regurgitate), here's a nice deep clone object copier I found on The Code Project a while ago and incorporated it in our stuff.
(虽然标准做法是实现ICloneable
接口( 在此进行了介绍,所以我不会反驳),但我还是在一段时间前在The Code Project上发现了一个不错的深克隆对象复印机,并将其合并到我们的资料中。)
As mentioned elsewhere, it does require your objects to be serializable.
(如在其他地方提到的,它确实要求您的对象可序列化。)
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
/// <summary>
/// Reference Article http://www.codeproject.com/KB/tips/SerializedObjectCloner.aspx
/// Provides a method for performing a deep copy of an object.
/// Binary Serialization is used to perform the copy.
/// </summary>
public static class ObjectCopier
{
/// <summary>
/// Perform a deep Copy of the object.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T Clone<T>(T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", nameof(source));
}
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
IFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream();
using (stream)
{
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
}
The idea is that it serializes your object and then deserializes it into a fresh object.
(这个想法是先序列化您的对象,然后反序列化为一个新的对象。)
The benefit is that you don't have to concern yourself about cloning everything when an object gets too complex. (这样做的好处是,当对象变得太复杂时,您不必担心克隆所有内容。)
And with the use of extension methods (also from the originally referenced source):
(并使用扩展方法(也来自最初引用的源):)
In case you prefer to use the new extension methods of C# 3.0, change the method to have the following signature:
(如果您更喜欢使用C#3.0的新扩展方法 ,请将方法更改为具有以下签名:)
public static T Clone<T>(this T source)
{
//...
}
Now the method call simply becomes objectBeingCloned.Clone();
(现在,方法调用就变成了objectBeingCloned.Clone();
)
. (。)
EDIT (January 10 2015) Thought I'd revisit this, to mention I recently started using (Newtonsoft) Json to do this, it should be lighter, and avoids the overhead of [Serializable] tags.
(编辑 (2015年1月10日)以为我会重新审视这一点,我最近提到开始使用(Newtonsoft)Json来做到这一点,它应该更轻巧,并且避免了[Serializable]标签的开销。)
( NB @atconway has pointed out in the comments that private members are not cloned using the JSON method) (( NB @atconway在注释中指出,不使用JSON方法克隆私有成员))
/// <summary>
/// Perform a deep Copy of the object, using Json as a serialisation method. NOTE: Private members are not cloned using this method.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T CloneJson<T>(this T source)
{
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
// initialize inner objects individually
// for example in default constructor some list property initialized with some values,
// but in 'source' these items are cleaned -
// without ObjectCreationHandling.Replace default constructor values will be added to result
var deserializeSettings = new JsonSerializerSettings {ObjectCreationHandling = ObjectCreationHandling.Replace};
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source), deserializeSettings);
}