Я должен реализовать метод расширенного расширения extclone, который можно использовать с любым экземпляром ссылочного типа, чтобы получить его глубокую копию. Я использую его как следующее:Реализация объектного глубокого клонирования
static class ClassCopy
{
static public T DeepClone<T> (this T instance)
{
if (instance == null) return null;
var type = instance.GetType();
T copy;
var flags = BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Instance;
var fields = type.GetFields(flags);
// If type is serializable - create instance copy using BinaryFormatter
if (type.IsSerializable)
{
using (var stream = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(stream, instance);
stream.Position = 0;
copy = (T) formatter.Deserialize(stream);
}
// Copy all fiels which are not marked as serializable
foreach (var field in fields)
{
if (!field.IsNotSerialized) continue;
var value = field.GetValue(instance);
//Recursion!!!
//for each embedded object also create deep copy
value = value != null ? value.DeepClone() : value;
field.SetValue(copy, value);
}
}
else
{
// If type is not serializable - create instance copy using Activator
//(if there is default constructor)
// or FormatterServices (if there is no constractor)
copy = CreateInstance<T>(type);
foreach (var field in fields)
{
var value = field.GetValue(instance);
//Recursion!!!
value = value != null ? value.DeepClone() : value;
field.SetValue(copy, value);
}
}
//Copy all properties
//In order to copy all backing fields for auto-implemented properties
var properties = type.GetProperties(flags|BindingFlags.SetProperty);
foreach (var property in properties)
{
if (property.CanWrite)
{
var value = property.GetValue(instance);
//Recursion!!!
value = value != null ? value.DeepClone() : null;
property.SetValue(copy, value);
}
}
return copy;
}
private static T CreateInstance<T>(Type t) where T: class
{
T instance;
var constructor = t.GetConstructor(Type.EmptyTypes);
if (constructor != null)
{
instance = Activator.CreateInstance(t) as T;
return instance;
}
instance = FormatterServices.GetUninitializedObject(t) as T;
return instance;
}
}
Он хорошо работает. Но если объект клонирован и его ссылочные типы полей имеют взаимные ссылки, этот код приводит к бесконечным циклам. , например.
private static void Main(string[] args)
{
var parent = new Parent();
parent.Child = new Child();
parent.Child.Parent = parent;
//Infinite Loop!!!
var parent1 = parent.DeepClone();
}
class Parent
{
public Child Child { get; set; }
}
class Child
{
public Parent Parent { get; set; }
}
Кто-нибудь знает, как реализовать эту задачу? Это должно быть реализовано буквально, и никакие вариации не допускаются (это практический курс). Большое спасибо за любые советы!
Есть причина, по которой вы не видите методы глубокого клонирования общего назначения.Чтобы быть выполненными правильно, они реалистично должны быть реализованы на основе конкретных типов, о которых идет речь. Учитывая, что вам очень нужно редко использовать такие реализации, это, как правило, не проблема. То, что вам нужно что-то подобное, на самом деле является признаком того, что что-то может быть неправильным. – Servy
Проверьте https://cloneextensions.codeplex.com/ – MarcinJuraszek
Вы можете попробовать этот код: http://code.msdn.microsoft.com/CSEFDeepCloneObject-12a5cb95 –