C # 직렬화 프레임 워크를 사용하여 참조 수정 (사후 처리)을 수행하려면 어떻게해야합니까?
다른 개체를 참조하는 개체가있는 개체 그래프가 있습니다. 그들은 모두 ISerializable
인터페이스를 구현하고 모두 인스턴스 ID를 가지고 있으므로 직렬화 된 상태에서 참조를 나타내는 것은 쉽습니다.
krux는 역 직렬화 생성자가 호출 될 때 해당 개체가 참조하는 모든 개체가 역 직렬화되지 않았을 수 있으므로 참조를 유효한 개체로 설정할 수 없다는 것입니다. 그리고 참조 수정을 수행하기 위해 C # 직렬화 프레임 워크의 사후 처리 단계에 연결하는 방법을 찾을 수 없습니다. 그것을 할 방법이 있습니까?
요청에 따라 문제를 강조하는 인위적인 수업이 있습니다.
[Serializable]
public class Pony : ISerializable
{
public int Id { get; set; }
public string Name { get; set; }
public Pony BFF { get; set; }
public Pony() {}
private Pony(SerializationInfo info, StreamingContext context) {
Id = info.GetInt32("id");
Name = info.GetString("name");
var bffId = info.GetInt32("BFFId");
BFF = null; // <===== Fixup! Find Pony instance with id == bffId
}
public void GetObjectData(SerializationInfo info, StreamingContext ontext) {
info.AddValue("id", Id);
info.AddValue("name", Name);
info.AddValue("BFFId", BFF.Id);
}
}
다음은 (비) 직렬화 코드입니다.
var rd = new Pony { Id = 1, Name = "Rainbow Dash" };
var fs = new Pony { Id = 2, Name = "Fluttershy", BFF = rd };
rd.BFF = fs;
var ponies = new List<Pony>{ rd, fs };
Stream stream = new MemoryStream();
var formatter = new BinaryFormatter();
formatter.Serialize(stream, ponies);
stream.Seek(0, SeekOrigin.Begin);
var deserializedPonies = (List<Pony>)formatter.Deserialize(stream);
이 질문은 내 문제를 해결하지 못합니다. .net XML Serialization-Object Copy 대신 참조 저장
BinaryFormatter + ISerializable 프레임 워크를 직렬화에 사용하고 XmlFormater로 전환하지 않고 싶습니다.
이 목적을위한 속성이 있습니다.
역 직렬화하려는 개체에서 다음 메서드를 구현합니다.
[OnDeserialized]
internal void OnDeserializedMethod(StreamingContext context) {
}
System.Runtime.Serialization
도움이 될 수있는 몇 가지 속성이 더 있습니다.
편집하다
코드를 약간 수정했습니다.
[Serializable]
public class Pony {
public int Id {
get; set;
}
public string Name {
get; set;
}
public Pony BFF {
get; set;
}
public Pony() {
}
[OnDeserialized]
internal void OnDeserializedMethod(StreamingContext context) {
Console.WriteLine(this.Id + " " + this.Name + " " + this.BFF?.Name);
}
}
실험 방법:
var rd = new Pony { Id = 1, Name = "Rainbow Dash" };
var fs = new Pony { Id = 2, Name = "Fluttershy", BFF = rd };
rd.BFF = fs;
var ponies = new List<Pony> { rd, fs };
object returnValue;
using (var memoryStream = new MemoryStream()) {
var binaryFormatter = new BinaryFormatter();
binaryFormatter.Serialize(memoryStream, ponies);
memoryStream.Position = 0;
returnValue = binaryFormatter.Deserialize(memoryStream);
}
var xx = (List<Pony>)returnValue;
보시다시피 ISerializable
Interface, private contructor 및-Method를 제거했습니다 GetObjectData
.
나는 당신이 말하지 않은 것처럼 당신이 정말로 필요하다고 생각하지 않기 때문에 (De) Serialization을 구현했다고 생각합니다.
이 게시물은 또 다른 정보 소스입니다.
편집 2 (테스트 방법은 동일하게 유지됨) :
접근법 1 (전체 역 직렬화 및 직렬화) ...
private Pony(SerializationInfo info, StreamingContext context) {
foreach (SerializationEntry entry in info) {
switch (entry.Name) {
case "Id":
this.Id = (int)entry.Value;
break;
case "Name":
this.Name = (string)entry.Value;
break;
case "BFF":
this.BFF = (Pony)entry.Value;
break;
}
}
}
public void GetObjectData(SerializationInfo info, StreamingContext ontext) {
info.AddValue("Id", Id);
info.AddValue("Name", Name);
info.AddValue("BFF", BFF);
}
}
...
접근 방식 2 (재귀 객체-ID 만 해당) :
...
private Pony(SerializationInfo info, StreamingContext context) {
foreach (SerializationEntry entry in info) {
switch (entry.Name) {
case "Id":
this.Id = (int)entry.Value;
break;
case "Name":
this.Name = (string)entry.Value;
break;
case "BFF.Id":
var bffId = (int)entry.Value;
this.BFF = GetPonyById(bffId); // You have to implement this
break;
}
}
}
public void GetObjectData(SerializationInfo info, StreamingContext ontext) {
info.AddValue("Id", Id);
info.AddValue("Name", Name);
info.AddValue("BFF.Id", BFF.Id);
}
...
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다