2010-02-26 4 views
5

새 개체를 만들지 않고 표준 serializer 중 하나를 사용하여 개체 속성을 deserialize 할 수 있습니까?기존 개체에 속성 역 직렬화

문제는 문제가되는 객체가 매우 복잡합니다 (특수 팩토리에서만 생성 할 수 있으며 런타임에 해당 유형이 동적으로 생성 됨). 그러나 일부 알려진 속성이있어서 외부에 저장하려고합니다. 파일 (선호 xml,하지만 바이너리도 OK), 나중에 (아마도 응용 프로그램을 다시 시작한 후) 저장된 속성을 내가 제공하는 객체로 다시 설정해야합니다.

모든 표준 시리얼 라이저는 나를 위해 새 객체 (공용 매개 변수없는 생성자가 필요함) 만 생성 할 수있는 것 같습니다. 수동으로 모든 속성을 할당해야합니다. 직렬화 된 속성 집합이 상당히 커서 그리고 프로젝트 수명 기간 동안 몇 번 변경 될 것이므로 필자가 피하고 싶은 수동 직렬화와 크게 다르지 않습니다. 이 시점에서 필자는 저의 가벼운 시리얼 라이저를 작성하는 것에 매우 가깝습니다.하지만 누군가가 그런 일을하는 표준적인 방법을 제안 할 수 있습니까?

답변

3

protobuf-net에는 Serializer.Merge 메서드가 있습니다.이 메서드를 사용하면 기존 인스턴스로 deserialize 할 수 있습니다. 스트림에서 찾은 값만 기록됩니다 (객체를 지우지는 않음).

Microsoft는 아니지만 상당히 안정적입니다.

확장하려면; 모든 일반적인 시나리오를 처리하는 강력한 직렬화를 얻으려면 (나는 아픈 경험에서 알 수 있습니다) 많은 작업이 필요합니다. 가능한 한 기존 코드를 다시 사용하는 것이 좋습니다. protobuf-net은 필요한 모든 것을 제공하는 것 같습니다. 현재 바이너리는 클래스를 꾸미기 만하면됩니다 (WCF의 [DataContract]과 매우 유사합니다 - 사실 [DataContract]/[DataMember]도 지원합니다).하지만 POCO에 대해서도 작업 할 수 있도록 작업이되어 있으므로 외부에서 사용할 수 있습니다. 당신의 통제.

+0

요청한대로 속성 수준 대신 필드 수준에서 작동하지 않습니까? – Lucero

+0

@Lucero - 필드와 속성 모두에서 작동합니다. 그것은 당신이하는 말에 달려 있습니다. –

+0

흥미로운 링크를 가져 주셔서 감사합니다.하지만 다소 단순한 작업을 위해 완전히 새로운 타사 구성 요소를 사용하지 않으려합니다. 또한 단점은 xml이 아니라는 것입니다. – Chriso

0

직접 처리 할 수있는 유연한 "직렬 변환기"를 구현할 수 있습니다. 반사는 필요한 모든 것을 제공합니다.

0

당신은 당신은 FormatterServices 클래스를 사용할 수 있습니다 정확히이 작업을 위해 설계 될 것 같습니다 FormatterServices.PopulateObjectMembers 방법 ...

+1

그 시점에서, 당신은 이미 스트림을 파싱하여'object's, * and *로 값을 얻고,'MemberInfo's, *와 *는 서브 데이터의 모든 복잡성을 처리했습니다.솔직히 단순히 값을 설정하는 방법을 사용하는 것만으로는 충분하지 않습니다. 바로 그 시점에서 리플렉션을 사용할 수 있습니다. –

2

를 사용할 수 있습니다.

[Serializable] 
class Book 
{ 
    public string Title { get; set; } 

    public string Author { get; set; } 

    // Constructor for setting new values. 
    public Book(string title, string author) 
    { 
     Title = title; 
     Author = author; 
    } 
} 

당신은 이런 식으로 직렬화 할 수 있습니다 :

var book = new Book("Moby Dick", "Herman Melville"); 

string path = Path.GetTempFileName(); 

var bf = new BinaryFormatter(); 
using (var fs = new FileStream(path, FileMode.Create)) 
    bf.Serialize(fs, book); 

개체가 수정 된 경우 :

// Edit object 
book.Title = "Foo"; 
Console.WriteLine("{0}, {1}", book.Title, book.Author); 

당신은 그것을 복원 할 수 있습니다

당신은 클래스 예약이 다음 코드 :

Book temp; 
using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read)) 
    temp = (Book) bf.Deserialize(fs); 

MemberInfo[] members = FormatterServices.GetSerializableMembers(typeof (Book)); 
FormatterServices.PopulateObjectMembers(book, members, FormatterServices.GetObjectData(temp, members)); 

// Object state is back 
Console.WriteLine("{0}, {1}", book.Title, book.Author);