Ответ 1
Serializable
требуется для BinaryFormatter
для работы.
DataContract
и DataMember
атрибут используются с DataContractSerializer
.
Вы можете украсить класс атрибутами для обоих сериализаторов.
Я пытаюсь создать глубокий клон объекта, используя следующий метод.
public static T DeepClone<T>(this T target)
{
using (MemoryStream stream = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, target);
stream.Position = 0;
return (T)formatter.Deserialize(stream);
}
}
Этот метод требует объекта, который является Сериализованным, то есть объектом класса, который имеет на нем атрибут "Serializable" . У меня есть класс, который имеет атрибут "DataContract" , но метод не работает с этим атрибутом. Я думаю, что "DataContract" также является сериализатором, но, возможно, отличается от типа "Serializable" .
Может ли кто-нибудь объяснить мне разницу между ними? Также, пожалуйста, дайте мне знать, возможно ли создать глубокий клик объекта с одним атрибутом, который выполняет работу как с атрибутом "DataContract" , так и с "Serializable" или может быть другим способом создания глубокого изображения?
Пожалуйста, помогите!
Serializable
требуется для BinaryFormatter
для работы.
DataContract
и DataMember
атрибут используются с DataContractSerializer
.
Вы можете украсить класс атрибутами для обоих сериализаторов.
DataContract
используется в WCF, поэтому .NET 3.0+. В .net 2.0 или ниже нет атрибута DataContract, DataMember
, только Serializable
.
Как сказал Oded, если вы хотите использовать BinaryFormatter, вам нужно украсить тип Serializable.
Я однажды осмотрел структуру объекта через 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 _supported путем десериализации. Кроме того, каждый объект в иерархии будет разбит, если его конструктор класса должен инициализировать что-либо, кроме установки всех полей. Последняя точка работает только с сериализацией, если класс имеет соответствующую реализацию, например. метод, отмеченный [OnDeserialized]
, реализует ISerializable
,....