Однажды я сделал некоторую проверку структуры объекта через Reflection, чтобы найти все сборки, необходимые для десериализации, и сериализовать их вместе с начальной загрузкой.
Немного потрудившись, можно создать аналогичный метод для глубокого копирования.По сути, вам нужен рекурсивный метод, который ведет словарь для обнаружения циклических ссылок.Внутри метода вы проверяете все поля примерно так:
private void InspectRecursively(object input,
Dictionary<object, bool> processedObjects)
{
if ((input != null) && !processedObjects.ContainsKey(input))
{
processedObjects.Add(input, true);
List<FieldInfo> fields = type.GetFields(BindingFlags.Instance |
BindingFlags.Public | BindingFlags.NonPublic );
foreach (FieldInfo field in fields)
{
object nextInput = field.GetValue(input);
if (nextInput is System.Collections.IEnumerable)
{
System.Collections.IEnumerator enumerator = (nextInput as
System.Collections.IEnumerable).GetEnumerator();
while (enumerator.MoveNext())
{
InspectRecursively(enumerator.Current, processedObjects);
}
}
else
{
InspectRecursively(nextInput, processedObjects);
}
}
}
}
Чтобы все заработало, вам нужно добавить объект вывода и что-то вроде System.Runtime.Serialization.FormatterServices.GetUninitializedObject(Type type)
, чтобы создать самую мелкую копию (даже без копирования ссылок)значение каждого поля.Наконец, вы можете установить для каждого поля что-то вроде field.SetValue(input, output)
Однако эта реализация не поддерживает зарегистрированные обработчики событий, что также поддерживается десериализацией _ un _.Кроме того, каждый объект в иерархии будет нарушен, если конструктор его класса должен что-либо инициализировать, кроме установки всех полей.Последний пункт работает только с сериализацией, если класс имеет соответствующую реализацию, например, метод, помеченный [OnDeserialized]
, реализует ISerializable
, ....