Beispiel zu stark typisierten Erweiterungen

Für das Beispiel wird die SyndicationFeed-Klasse verwendet.Die in diesem Beispiel gezeigten Muster können jedoch in allen Syndication-Klassen verwendet werden, die Erweiterungsdaten unterstützen.

Das Syndication-Objektmodell (SyndicationFeed, SyndicationItem und verwandte Klassen) unterstützt lose typisierten Zugriff auf Erweiterungsdaten mithilfe der AttributeExtensions-Eigenschaft und der ElementExtensions-Eigenschaft.In diesem Beispiel wird das Bereitstellen eines stark typisierten Zugriffs auf Erweiterungsdaten veranschaulicht, indem benutzerdefinierte, von SyndicationFeed und SyndicationItem abgeleitete Klassen implementiert werden, die bestimmte anwendungsspezifische Erweiterungen als stark typisierte Eigenschaften verfügbar machen.

Außerdem wird als Beispiel veranschaulicht, wie ein im vorgeschlagenen RFC zu Atom-Threading-Erweiterungen definiertes Erweiterungselement definiert wird.Dies dient nur zur Veranschaulichung. Das Beispiel ist keine vollständige Implementierung der vorgeschlagenen Spezifikation.

Beispiel-XML

Das folgende XML-Beispiel zeigt einen Atom 1.0-Eintrag mit einem zusätzlichen <in-reply-to>-Erweiterungselement.

<entry>  
    <id>tag:example.org,2005:1,2</id>  
    <title type="text">Another response to the original</title>  
    <summary type="text">  
         This is a response to the original entry</summary>  
    <updated>2006-03-01T12:12:13Z</updated>  
    <link href="http://www.example.org/entries/1/2" />  
    <in-reply-to p3:ref="tag:example.org,2005:1"   
                 p3:href="http://www.example.org/entries/1"   
                 p3:type="application/xhtml+xml"   
                 xmlns:p3="http://contoso.org/syndication/thread/1.0"   
                 xmlns="http://contoso.org/syndication/thread/1.0">  
      <anotherElement xmlns="http://www.w3.org/2005/Atom">  
                     Some more data</anotherElement>  
      <aDifferentElement xmlns="http://www.w3.org/2005/Atom">  
                     Even more data</aDifferentElement>  
    </in-reply-to>  
</entry>  

Das <in-reply-to>-Element gibt drei erforderliche Attribute an (ref, type und href) und lässt außerdem das Vorhandensein weiterer Erweiterungsattribute und Erweiterungselemente zu.

Modellieren des In-Reply-To-Elements

In diesem Beispiel wird das <in-reply-to>-Element als CLR modelliert, das IXmlSerializable implementiert. Dabei wird die Verwendung mit DataContractSerializer ermöglicht.Außerdem werden einige Methoden und Eigenschaften für den Zugriff auf die Daten des Elements implementiert, wie im folgenden Beispielcode dargestellt.

[XmlRoot(ElementName = "in-reply-to", Namespace = "http://contoso.org/syndication/thread/1.0")]  
public class InReplyToElement : IXmlSerializable  
{  
    internal const string ElementName = "in-reply-to";  
    internal const string NsUri =   
                  "http://contoso.org/syndication/thread/1.0";  
    private Dictionary<XmlQualifiedName, string> extensionAttributes;  
    private Collection<XElement> extensionElements;  

    public InReplyToElement()  
    {  
        this.extensionElements = new Collection<XElement>();  
        this.extensionAttributes = new Dictionary<XmlQualifiedName,   
                                                          string>();  
    }  

    public Dictionary<XmlQualifiedName, string> AttributeExtensions  
    {  
        get { return this.extensionAttributes; }  
    }  

    public Collection<XElement> ElementExtensions  
    {  
        get { return this.extensionElements; }  
    }  

    public Uri Href  
    { get; set; }  

    public string MediaType  
    { get; set; }  

    public string Ref  
    { get; set; }  

    public Uri Source  
    { get; set; }  
}  

Die InReplyToElement-Klasse implementiert Eigenschaften für das erforderliche Attribut (HRef, MediaType und Source) sowie Auflistungen für AttributeExtensions und ElementExtensions.

Die InReplyToElement-Klasse implementiert die IXmlSerializable-Schnittstelle, mit der direkt gesteuert werden kann, wie Objektinstanzen aus XML gelesen und in XML geschrieben werden.Die ReadXml-Methode liest zuerst Werte für die Eigenschaften Ref, HRef, Source und MediaType aus dem übergebenen XmlReader.Alle unbekannten Attribute werden in der AttributeExtensions-Auflistung gespeichert.Wenn alle Attribute gelesen wurden, wird ReadStartElement() aufgerufen, um den Reader an das nächste Element weiterzugeben.Da das von dieser Klasse modellierte Element keine erforderlichen untergeordneten Elemente aufweist, werden untergeordnete Elemente in XElement-Instanzen gepuffert und in der ElementExtensions-Auflistung gespeichert, wie im folgenden Code dargestellt.

public void ReadXml(System.Xml.XmlReader reader)  
{  
    bool isEmpty = reader.IsEmptyElement;  

    if (reader.HasAttributes)  
    {  
        for (int i = 0; i < reader.AttributeCount; i++)  
        {  
            reader.MoveToNextAttribute();  

            if (reader.NamespaceURI == "")  
            {  
                if (reader.LocalName == "ref")  
                {  
                    this.Ref = reader.Value;  
                }  
                else if (reader.LocalName == "href")  
                {  
                    this.Href = new Uri(reader.Value);  
                }  
                else if (reader.LocalName == "source")  
                {  
                    this.Source = new Uri(reader.Value);  
                }  
                else if (reader.LocalName == "type")  
                {  
                    this.MediaType = reader.Value;  
                }  
                else  
                {  
                    this.AttributeExtensions.Add(new   
                                 XmlQualifiedName(reader.LocalName,   
                                 reader.NamespaceURI),   
                                 reader.Value);  
                }  
            }  
        }  
    }  

    reader.ReadStartElement();  

    if (!isEmpty)  
    {  
        while (reader.IsStartElement())  
        {  
            ElementExtensions.Add(  
                  (XElement) XElement.ReadFrom(reader));  
        }  
        reader.ReadEndElement();  
    }  
}  

In WriteXml schreibt die InReplyToElement-Methode zuerst die Werte der Eigenschaften Ref, HRef, Source und MediaType als XML-Attribute (WriteXml ist nicht zuständig für das Schreiben des tatsächlichen äußeren Elements wie beim Aufrufer von WriteXml).Außerdem wird auch der Inhalt von AttributeExtensions und ElementExtensions an den Writer geschrieben, wie im folgenden Code dargestellt.

public void WriteXml(System.Xml.XmlWriter writer)  
{  
    if (this.Ref != null)  
    {  
        writer.WriteAttributeString("ref", InReplyToElement.NsUri,   
                                            this.Ref);  
    }  
    if (this.Href != null)  
    {  
        writer.WriteAttributeString("href", InReplyToElement.NsUri,   
                                                this.Href.ToString());  
    }  
    if (this.Source != null)  
    {  
        writer.WriteAttributeString("source", InReplyToElement.NsUri,   
                                              this.Source.ToString());  
    }  
    if (this.MediaType != null)  
    {  
        writer.WriteAttributeString("type", InReplyToElement.NsUri,   
                                                    this.MediaType);  
    }  

    foreach (KeyValuePair<XmlQualifiedName, string> kvp in   
                                             this.AttributeExtensions)  
    {  
        writer.WriteAttributeString(kvp.Key.Name, kvp.Key.Namespace,   
                                                   kvp.Value);  
    }  

    foreach (XElement element in this.ElementExtensions)  
    {  
        element.WriteTo(writer);  
    }  
}  

ThreadedFeed und ThreadedItem

Im Beispiel werden SyndicationItems mit InReplyTo-Erweiterungen von der ThreadedItem-Klasse modelliert.Entsprechend handelt es sich bei der ThreadedFeed-Klasse um einen SyndicationFeed, dessen Elemente Instanzen von ThreadedItem sind.

Die ThreadedFeed-Klasse erbt von SyndicationFeed und überschreibt OnCreateItem, um ein ThreadedItem zurückzugeben.Außerdem wird eine Methode zum Zugriff auf die Items-Auflistung als ThreadedItems implementiert, wie im folgenden Code dargestellt.

public class ThreadedFeed : SyndicationFeed  
{  
    public ThreadedFeed()  
    {  
    }  

    public IEnumerable<ThreadedItem> ThreadedItems  
    {  
        get  
        {  
            return this.Items.Cast<ThreadedItem>();  
        }  
    }  

    protected override SyndicationItem CreateItem()  
    {  
        return new ThreadedItem();  
    }  
}  

Die Klasse ThreadedItem erbt von SyndicationItem und legt InReplyToElement als stark typisierte Eigenschaft fest.So kann bequem programmgesteuert auf die InReplyTo-Erweiterungsdaten zugegriffen werden.Außerdem werden TryParseElement und WriteElementExtensions für das Lesen und Schreiben der Erweiterungsdaten implementiert, wie im folgenden Code dargestellt.

public class ThreadedItem : SyndicationItem  
{  
    private InReplyToElement inReplyTo;  
    // Constructors  
        public ThreadedItem()  
        {  
            inReplyTo = new InReplyToElement();  
        }  

        public ThreadedItem(string title, string content, Uri itemAlternateLink, string id, DateTimeOffset lastUpdatedTime) : base(title, content, itemAlternateLink, id, lastUpdatedTime)  
        {  
            inReplyTo = new InReplyToElement();  
        }  

    public InReplyToElement InReplyTo  
    {  
        get { return this.inReplyTo; }  
    }  

    protected override bool TryParseElement(  
                        System.Xml.XmlReader reader,   
                        string version)  
    {  
        if (version == SyndicationVersions.Atom10 &&  
            reader.NamespaceURI == InReplyToElement.NsUri &&  
            reader.LocalName == InReplyToElement.ElementName)  
        {  
            this.inReplyTo = new InReplyToElement();  

            this.InReplyTo.ReadXml(reader);  

            return true;  
        }  
        else  
        {  
            return base.TryParseElement(reader, version);  
        }  
    }  

    protected override void WriteElementExtensions(XmlWriter writer,   
                                                 string version)  
    {  
        if (this.InReplyTo != null &&   
                     version == SyndicationVersions.Atom10)  
        {  
            writer.WriteStartElement(InReplyToElement.ElementName,   
                                           InReplyToElement.NsUri);  
            this.InReplyTo.WriteXml(writer);  
            writer.WriteEndElement();  
        }  

        base.WriteElementExtensions(writer, version);  
    }  
}  

So richten Sie das Beispiel ein, erstellen es und führen es aus

  1. Stellen Sie sicher, dass Sie die Einmaliges Setupverfahren für Windows Communication Foundation-Beispiele ausgeführt haben.

  2. Folgen Sie zum Erstellen der C#- bzw. Visual Basic .NET-Version der Projektmappe den Anweisungen unter Erstellen der Windows Communication Foundation-Beispiele.

  3. Um das Beispiel in einer Konfiguration mit einem Computer oder computerübergreifend auszuführen, befolgen Sie die Anweisungen unter Durchführen der Windows Communication Foundation-Beispiele.

Wichtig

Die Beispiele sind möglicherweise bereits auf dem Computer installiert.Suchen Sie nach dem folgenden Verzeichnis (Standardverzeichnis), bevor Sie fortfahren.

<Installationslaufwerk>:\WF_WCF_Samples

Wenn dieses Verzeichnis nicht vorhanden ist, rufen Sie Windows Communication Foundation (WCF) and Windows Workflow Foundation (WF) Samples for .NET Framework 4 auf, um alle Windows Communication Foundation (WCF)- und WF-Beispiele herunterzuladen.Dieses Beispiel befindet sich im folgenden Verzeichnis.

<InstallDrive>:\WF_WCF_Samples\WCF\Extensibility\Syndication\StronglyTypedExtensions

Siehe auch