2009-02-26 6 views
14

Jeśli mam klasa oznaczona jako DataContract i kilka obiektów na nim zaznaczone DataMember atrybutów mogę szeregować go do XML łatwo, ale byłoby stworzyć wyjście jak:W jaki sposób można sterować serializacją .NET DataContract, aby używał atrybutów XML zamiast elementów?

<Person> 
    <Name>John Smith</Name> 
    <Email>[email protected]</Email> 
    <Phone>123-123-1234</Phone> 
</Person> 

Co wolałbym to atrybuty jak ...

<Person Name="John Smith" Email="[email protected]" Phone="123-123-1234" /> 

Atrybut DataMember pozwala mi kontrolować Imię i zamówienie, ale nie tego, czy jest szeregowane jako elementu lub atrybutu. Rozejrzałem się i znalazłem DataContractFormat i IXmlSerializable, ale mam nadzieję, że istnieje łatwiejsze rozwiązanie.

Jaki jest najprostszy sposób to zrobić?

+0

Potrzebuję XML do działania w ten sposób, podczas gdy JSON kontynuuje pracę. – Brennan

Odpowiedz

11

Nie można tego zrobić z DataContractSerializer; jeśli chcesz mieć atrybuty, musisz użyć wartości XmlSerializer. Dzięki klasie DataContractSerializer dozwolony jest bardziej restrykcyjny podzbiór specyfikacji XML, co poprawia wydajność i poprawia współdziałanie opublikowanych usług, ale daje mniejszą kontrolę nad formatem XML.

Jeśli korzystasz z usług WCF, spójrz na XmlSerializerFormatAttribute, który umożliwia korzystanie z XmlSerializer do serializacji.

+1

Musi istnieć prosty sposób na wykorzystanie atrybutów. Nie dbam o usługi sieciowe, po prostu wyprowadzam plik XML w określonym formacie. – Brennan

+0

Witam, obawiam się, że Greg ma rację - zobacz http://msdn.microsoft.com/en-us/library/ms731923.aspx dla ograniczeń DataContractSerializer. – larsw

+1

Jeśli nie zależy Ci na usługach internetowych, to dlaczego używasz WCF? Czy próbujesz serializować niektóre klasy? Jeśli tak, użyj samego XmlSerializer. –

34

Można to zrobić z DataContractSerializer - odpowiedź jest przejąć serializacji Xml siebie poprzez wdrożenie IXmlSerializable interfejs . Dla zapisu tylko wsparcie - można zostawić realizację z ReadXml pusty, a zwróci null dla GetSchema, a następnie napisać realizację WriteXml następująco:

public class MyPerson : IXmlSerializable 
{ 
    public string Name { get; set;} 
    public string Email { get; set;} 
    public string Phone { get; set;} 

    public XmlSchema GetSchema() { return null; } 
    public void ReadXml(XmlReader reader) { } 
    public void WriteXml(XmlWriter writer) 
    { 
    writer.WriteAttributeString("name", Name); 
    writer.WriteAttributeString("email", Email); 
    writer.WriteAttributeString("phone", Phone); 
    } 
} 

Jeśli używasz to samo typ, na przykład serializacja JSON, możesz nadal dodawać atrybuty DataContract i DataMember - DataContractSerializer będzie wykorzystywał implementację interfejsu IXmlSerializable tylko podczas pisania Xml.

Zapisałem na blogu o tym here.

+0

Czy jesteś pewien, że 'DataContractSerializer' wywoła metodę' WriteXml' tego kodu? –

+1

Wiem - wydaje mi się to nieprawdopodobne - ale właśnie opublikowałem artykuł na naszym blogu korporacyjnym na stronie http: //www.labs.jobserve.com/Articles.aspx/Building-Labs - Writing-an-OpenSearch-Suggestions-provider-in-C-with-WCF gdzie możesz pobrać kod źródłowy, który pokazuje go w akcji (używając go do implementacji sugestii OpenSearch). Wskazówki pochodziły z tej zawartości MSDN: http://msdn.microsoft.com/en-us/library/ms731923.aspx. –

+0

Należy również zapoznać się z http://msdn.microsoft.com/en-us/library/aa347876.aspx. –

0

Można dokonać konwersji między atrybutami i elementami podczas serializacji/deserializacji. Następujące prace dla tego ostatniego.

private XmlReader AttributesToElements(Stream stream) 
    { 
      var root = XElement.Load(stream); 
      foreach (var element in root.Descendants()) { 
        foreach (var attribute in element.Attributes()) 
          element.Add(new XElement(root.Name.Namespace + attribute.Name.LocalName, (string)attribute)); 
        element.Attributes().Remove(); 
      } 
      return root.CreateReader(); 
    } 
Powiązane problemy