Beispiel zu stark typisierten ErweiterungenStrongly-Typed Extensions Sample

Für das Beispiel wird die SyndicationFeed-Klasse verwendet.The sample uses the SyndicationFeed class for the purposes of the example. Die in diesem Beispiel gezeigten Muster können jedoch in allen Syndication-Klassen verwendet werden, die Erweiterungsdaten unterstützen.However, the patterns demonstrated in this sample can be used with all of the Syndication classes that support extension data.

Das Syndication-Objektmodell (SyndicationFeed, SyndicationItem und verwandte Klassen) unterstützt lose typisierten Zugriff auf Erweiterungsdaten mithilfe der AttributeExtensions-Eigenschaft und der ElementExtensions-Eigenschaft.The Syndication object model (SyndicationFeed, SyndicationItem, and related classes) supports loosely-typed access to extension data by using the AttributeExtensions and ElementExtensions properties. 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.This sample shows how to provide strongly-typed access to extension data by implementing custom derived classes of SyndicationFeed and SyndicationItem that make available certain application-specific extensions as strongly-typed properties.

Außerdem wird als Beispiel veranschaulicht, wie ein im vorgeschlagenen RFC zu Atom-Threading-Erweiterungen definiertes Erweiterungselement definiert wird.As an example, this sample shows how to implement an extension element defined in the proposed Atom Threading Extensions RFC. Dies dient nur zur Veranschaulichung. Das Beispiel ist keine vollständige Implementierung der vorgeschlagenen Spezifikation.This is for demonstration purposes only and this sample is not intended to be a full implementation of the proposed specification.

Beispiel-XMLSample XML

Das folgende XML-Beispiel zeigt einen Atom 1.0-Eintrag mit einem zusätzlichen <in-reply-to>-Erweiterungselement.The following XML example shows an Atom 1.0 entry with an additional <in-reply-to> extension element.

<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>  

Die <in-reply-to> -Element gibt drei erforderliche Attribute (ref, type und href) und lässt außerdem das Vorhandensein weiterer Erweiterungsattribute und Erweiterungselemente.The <in-reply-to> element specifies three required attributes (ref, type and href) while also allowing for the presence of additional extension attributes and extension elements.

Modellieren des In-Reply-To-ElementsModeling the In-Reply-To element

In diesem Beispiel wird das <in-reply-to>-Element als CLR modelliert, das IXmlSerializable implementiert. Dabei wird die Verwendung mit DataContractSerializer ermöglicht.In this sample, the <in-reply-to> element is modeled as CLR that implements IXmlSerializable, which enables its use with the DataContractSerializer. Außerdem werden einige Methoden und Eigenschaften für den Zugriff auf die Daten des Elements implementiert, wie im folgenden Beispielcode dargestellt.It also implements some methods and properties for accessing the element’s data, as shown in the following sample code.

[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.The InReplyToElement class implements properties for the required attribute (HRef, MediaType, and Source) as well as collections to hold AttributeExtensions and ElementExtensions.

Die InReplyToElement-Klasse implementiert die IXmlSerializable-Schnittstelle, mit der direkt gesteuert werden kann, wie Objektinstanzen aus XML gelesen und in XML geschrieben werden.The InReplyToElement class implements the IXmlSerializable interface, which allows direct control over how object instances are read from and written to XML. Die ReadXml-Methode liest zuerst Werte für die Eigenschaften Ref, HRef, Source und MediaType aus dem übergebenen XmlReader.The ReadXml method first reads the values for the Ref, HRef, Source, and MediaType properties from the XmlReader passed to it. Alle unbekannten Attribute werden in der AttributeExtensions-Auflistung gespeichert.Any unknown attributes are stored in the AttributeExtensions collection. Wenn alle Attribute gelesen wurden, wird ReadStartElement() aufgerufen, um den Reader an das nächste Element weiterzugeben.When all the attributes have been read, ReadStartElement() is called to advance the reader to the next element. 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.Because the element modeled by this class has no required children, the child elements get buffered into XElement instances and stored in the ElementExtensions collection, as shown in the following code.

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).In WriteXml, the InReplyToElement method first writes out the values of the Ref, HRef, Source, and MediaType properties as XML attributes (WriteXml is not responsible for writing the actual outer element itself, as that done by the caller of WriteXml). Außerdem wird auch der Inhalt von AttributeExtensions und ElementExtensions an den Writer geschrieben, wie im folgenden Code dargestellt.It also writes the contents of the AttributeExtensions and ElementExtensions to the writer, as shown in the following code.

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 ThreadedItemThreadedFeed and ThreadedItem

Im Beispiel werden SyndicationItems mit InReplyTo-Erweiterungen von der ThreadedItem-Klasse modelliert.In the sample, SyndicationItems with InReplyTo extensions are modeled by the ThreadedItem class. Entsprechend handelt es sich bei der ThreadedFeed-Klasse um einen SyndicationFeed, dessen Elemente Instanzen von ThreadedItem sind.Similarly, the ThreadedFeed class is a SyndicationFeed whose items are all instances of ThreadedItem.

Die ThreadedFeed-Klasse erbt von SyndicationFeed und überschreibt OnCreateItem, um ein ThreadedItem zurückzugeben.The ThreadedFeed class inherits from SyndicationFeed and overrides OnCreateItem to return a ThreadedItem. Außerdem wird eine Methode zum Zugriff auf die Items-Auflistung als ThreadedItems implementiert, wie im folgenden Code dargestellt.It also implements a method for accessing the Items collection as ThreadedItems, as shown in the following code.

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.The class ThreadedItem inherits from SyndicationItem and makes InReplyToElement as a strongly-typed property. So kann bequem programmgesteuert auf die InReplyTo-Erweiterungsdaten zugegriffen werden.This provides for convenient programmatic access to the InReplyTo extension data. Außerdem werden TryParseElement und WriteElementExtensions für das Lesen und Schreiben der Erweiterungsdaten implementiert, wie im folgenden Code dargestellt.It also implements TryParseElement and WriteElementExtensions for reading and writing its extension data, as shown in the following code.

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 können Sie das Beispiel einrichten, erstellen und ausführenTo set up, build, and run the sample

  1. Stellen Sie sicher, dass Sie ausgeführt haben die Setupprozedur für die Windows Communication Foundation-Beispiele zum einmaligen.Ensure that you have performed the One-Time Setup Procedure for the Windows Communication Foundation Samples.

  2. Um die C#- oder Visual Basic .NET-Edition der Projektmappe zu erstellen, befolgen Sie die unter Building the Windows Communication Foundation Samplesaufgeführten Anweisungen.To build the C# or Visual Basic .NET edition of the solution, follow the instructions in Building the Windows Communication Foundation Samples.

  3. Um das Beispiel in einer einzelnen oder computerübergreifenden Konfiguration ausführen möchten, folgen Sie den Anweisungen Ausführen der Windows Communication Foundation-Beispiele.To run the sample in a single- or cross-machine configuration, follow the instructions in Running the Windows Communication Foundation Samples.

Wichtig

Die Beispiele sind möglicherweise bereits auf dem Computer installiert.The samples may already be installed on your computer. Suchen Sie nach dem folgenden Verzeichnis (Standardverzeichnis), bevor Sie fortfahren.Check for the following (default) directory before continuing.

<InstallDrive>:\WF_WCF_Samples

Wenn dieses Verzeichnis nicht vorhanden ist, fahren Sie mit Windows Communication Foundation (WCF) und Windows Workflow Foundation (WF) Samples for .NET Framework 4 aller Windows Communication Foundation (WCF) herunterladen und WFWF Beispiele.If this directory does not exist, go to Windows Communication Foundation (WCF) and Windows Workflow Foundation (WF) Samples for .NET Framework 4 to download all Windows Communication Foundation (WCF) and WFWF samples. Dieses Beispiel befindet sich im folgenden Verzeichnis.This sample is located in the following directory.

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

Siehe auchSee Also