2011-09-05 3 views
0

두 가지 다른 방법으로 단일 클래스를 저장하는 C# XmlSerialization API를 사용할 수 있습니까? 내가 직렬화가 저장되는 부분을 제어하기 위해 호출 할 때마다 - 예를두 가지 다른 방법으로 하나의 클래스를 저장하는 C# xml 직렬화 - 가능합니까?

나는 두 부분으로 (지정된 속성을 가진 그룹)에 클래스 필드를 분할하는 방법을 방법을 가지고 싶습니다
class Test 
{ 
    int group1_attr1; 
    int group1_attr2; 
    int group2_attr1; 
} 

를 들어 . 그룹 2

<?xml version="1.0" encoding="utf-8"?> 
<Test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org /2001/XMLSchema"> 
<group2_attr1>0</group2_attr1> 
</Test> 

로 저장 예를 들어 "깨끗한"방법으로 그것을 수행하는 방법 방법이 있나요

<?xml version="1.0" encoding="utf-8"?> 
<Test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org /2001/XMLSchema"> 
<group1_attr1>0</group1_attr1> 
<group1_attr2>0</group1_attr2> 
</Test> 

그룹 1로 저장하면? 아마도 xmlserialization에 없다면 바이너리일까요? 그런 다음이 두 파일을 Test의 단일 인스턴스로 병합하는 가장 좋은 방법은 무엇인지 알고 싶습니다. (group1과 group2의 입력란은 겹치지 않습니다.)

+0

가 왜 이러한 저장하지 않습니다를 propertys 목록에 /사전 및 직렬화하기 전에 컬렉션을 리필? 이것이 실제로 문제가된다면 재 설계를 고려해야합니다. – mbx

+0

다른 인터페이스의 속성 그룹을 설명하는 인터페이스를 만드는 경우 인터페이스 주도 XML 직렬화를 사용하여이 문제를 해결할 수 있습니다 (인터페이스는 다중 상속을 지원합니다). 그것에 대해 생각해보십시오. 건배;) –

답변

1

원하는대로 직렬화하는 방법을 보여주는 코드는 있지만 기존 인스턴스에 직렬화를 간단하게 수행 할 수 없으므로 직렬화가 어려워집니다 (How to use XmlSerializer to deserialize into an existing instance? 참조).

public class Test 
{ 
    public int group1_attr1; 
    public int group1_attr2; 
    public int group2_attr1; 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
    System.Xml.Serialization.XmlAttributes xa = 
     new System.Xml.Serialization.XmlAttributes(); 
    xa.XmlIgnore = true; 
    System.Xml.Serialization.XmlAttributeOverrides xo1 = 
     new System.Xml.Serialization.XmlAttributeOverrides(); 
    xo1.Add(typeof(Test), "group1_attr1", xa); 
    xo1.Add(typeof(Test), "group1_attr2", xa); 

    System.Xml.Serialization.XmlAttributeOverrides xo2 = 
     new System.Xml.Serialization.XmlAttributeOverrides(); 
    xo2.Add(typeof(Test), "group2_attr1", xa); 

    System.Xml.Serialization.XmlSerializer xs1 = 
     new System.Xml.Serialization.XmlSerializer(typeof(Test), xo1); 
    System.Xml.Serialization.XmlSerializer xs2 = 
     new System.Xml.Serialization.XmlSerializer(typeof(Test), xo2); 

    Test t1 = new Test(); 
    t1.group1_attr1 = 1; 
    t1.group1_attr2 = 2; 
    t1.group2_attr1 = 3; 
    using (System.IO.StringWriter sw = new System.IO.StringWriter()) 
    { 
     xs1.Serialize(sw, t1); 
     Console.WriteLine(sw); 
    } 

    using (System.IO.StringWriter sw = new System.IO.StringWriter()) 
    { 
     xs2.Serialize(sw, t1); 
     Console.WriteLine(sw); 
    } 
    } 
} 

역 직렬화 어쩌면 역 직렬화하기 전에 XML을 병합 할 수 있습니다 :

 Test t2 = new Test(); 
    System.Xml.Serialization.XmlSerializer xs3 = new System.Xml.Serialization.XmlSerializer(typeof(Test)); 
    string mergedXml = MergeSerializedXml(group1, group2); 

    using (System.IO.StringReader sr = new System.IO.StringReader(mergedXml)) 
    { 
     t2 = (Test)xs3.Deserialize(sr); 
    } 
... 

    static string MergeSerializedXml(string x1, string x2) 
    { 
    System.Xml.XmlDocument xd = new System.Xml.XmlDocument(); 
    xd.LoadXml(x1); 
    System.Xml.XmlReaderSettings xrs = new System.Xml.XmlReaderSettings(); 
    xrs.IgnoreWhitespace = true; 
    using (System.Xml.XmlReader xr = System.Xml.XmlReader.Create(new System.IO.StringReader(x2), xrs)) 
    { 
     while (xr.Read() && !xr.IsStartElement()) 
      ; 
     xr.MoveToContent(); 
     xr.Read(); 
     System.Xml.XmlNode xn = xd.ChildNodes[1]; 
     do 
     { 
      xn.AppendChild(xd.ReadNode(xr)); 
     } while (xr.NodeType != System.Xml.XmlNodeType.EndElement); 
    } 
    return xd.OuterXml; 
    } 
+0

감사합니다. XmlAttributeOverrides는 여기에서 묻기 전에 시도했지만 무언가 xa.XmlIgnore = true를 간과했습니다. 옵션 - 그 점을 지적 해 주셔서 감사합니다. 이제는 효과가있는 것 같습니다. 그것을 병합 할 때 - 당신이 제안한 것은 정확히 내 생각이었고 API에서 지원을 찾을 수 없었습니다. 귀하의 회신에서 나는 병합을 지원하는 직렬화 API에 실제로 존재하지 않는 것을 추론하므로 XML 병합이 가장 좋은 방법입니다. 다시 한 번 감사드립니다! (소스 코드는 내가 묻는 것보다 훨씬 많습니다.) – Peter

+0

@Peter - 여러분이 선호하는 답변으로 이것을 받아 들일 수 있습니다. 실제로 대답을하면 답을 표시 할 것입니다 (그리고 몇 가지 점, 또 다른 형태의 감사). 대답 된 질문을 생각해보십시오. – BlueMonkMN

0

작문으로이 작업을 수행 할 수 있습니다 (http://en.wikipedia.org/wiki/Composition_over_inheritance). CompositeGroup1을 직렬화하면 CompositeData의 인스턴스에 붙여야합니다. CompositeGroup2도 마찬가지입니다. 내장 시리얼 라이저를 사용하여 요청한대로 할 수있는 방법이 없습니다. 데이터를 serialize 할 때 항상 해당 유형의 전체 serialization을 생성합니다.

class CompositeData 
{ 
    public CompositeGroup1 Group1 { get; set; } 
    public CompositeGroup2 Group2 { get; set; } 
} 

class CompositeGroup1 
{ 
    public int Attr1 { get; set; } 
    public int Attr2 { get; set; } 
} 

class CompositeGroup2 
{ 
    public int Attr1 { get; set; } 
} 

또한, 각 그룹에 대해 하나의 추상 클래스를 구현 CompositeData을 고려할 수 있습니다. 런타임 형식 대신 전달 된 형식을 사용하여 직렬화 된 데이터를 생성하는 다른 JSON 직렬 변환기를 사용할 수 있습니다.

var json1 = serializer.Serialize<AbstractGroup1>(new CompositeData()); 
var json2 = serializer.Serialize<AbstractGroup2>(new CompositeData()); 

그러나 다시 함께 다시 배치하는 것은 여전히 ​​문제가됩니다.

0
당신이

가있을 수 있습니다대로 같은 문제를 해결하기 위해 인터페이스를 관용구를 사용 내 프로젝트, Xml Serialization Framework로 loook 수

예 :

클래스 인스턴스/개체를 serialize하려면

class Person 
{ 
    public string Name { get; set; } 
} 

당신은 아마 메타 데이터 기반의 XML 런타임 직렬화에 사용할 인터페이스를 선언 할 것이다 :이 프레임 워크는 심지어 특정 인터페이스/XML 형식을 사용하여 생활 인스턴스의 부분 업데이트 작업을 지원

interface IPersonRoot 
{ 
    string Name { get; set; } 
} 

[XmlRootSerializer("Body")] 
interface IPersonCustomRoot 
{ 
    string Name { get; set; } 
} 

interface IPersonCustomAttribute 
{ 
    [XmlAttributeRuntimeSerializer("Id")] 
    string Name { get; set; } 
} 

:에

를 /에서 XML 사용 IPersonRoot 인터페이스 :

 <Person> 
      <Name>John Doe</Name> 
     </Person> 

에/XML에서 IPersonCustomRoot 인터페이스를 사용하여 :

 <Body> 
      <Name>John Doe</Name> 
     </Body> 

에/XML에서 IPersonCustomAttribute 인터페이스 사용 :

 <Person Id="John Doe" /> 

이 좋은 하루 되세요,

건배)

아르투르 M.는

+0

그리고 원인은 코드가 적습니다. 당신은 그런 간단한 작업에 몇 시간을 허비하지 않았습니다. 이미 XML 직렬화 프레임 워크를 기반으로 인터페이스를 구축하는 데이 문제에 관심을 기울였습니다.) –

관련 문제