Dela via


Exempel på starkt skrivna tillägg

Exemplet StronglyTypedExtensions använder SyndicationFeed klassen i exemplet. De mönster som visas i det här exemplet kan dock användas med alla syndikeringsklasser som stöder tilläggsdata.

Syndikeringsobjektmodellen (SyndicationFeed, SyndicationItem och relaterade klasser) stöder löst skriven åtkomst till tilläggsdata med hjälp av egenskaperna AttributeExtensions och ElementExtensions. Det här exemplet visar hur du ger starkt typad åtkomst till tilläggsdata genom att implementera anpassade härledda klasser av SyndicationFeed och SyndicationItem som gör vissa programspecifika tillägg tillgängliga som starkt typade egenskaper.

Det här exemplet visar till exempel hur du implementerar ett tilläggselement som definierats i den föreslagna RFC:en för Atom Threading Extensions. Detta är endast i demonstrationssyfte och det här exemplet är inte avsett att vara ett fullständigt genomförande av den föreslagna specifikationen.

Xml-exempel

I följande XML-exempel visas en Atom 1.0-post med ytterligare ett <in-reply-to> tilläggselement.

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

Elementet <in-reply-to> anger tre obligatoriska attribut (reftypeoch href) samtidigt som det möjliggör förekomst av ytterligare tilläggsattribut och tilläggselement.

Att modellera In-Reply-To-elementet

I det här exemplet modelleras elementet <in-reply-to> som CLR som implementerar IXmlSerializable, vilket möjliggör dess användning med DataContractSerializer. Den implementerar också vissa metoder och egenskaper för att komma åt elementets data, enligt följande exempelkod.

[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; }
}

Klassen InReplyToElement implementerar egenskaper för det obligatoriska attributet (HRef, MediaType, och Source) samt samlingar som ska lagras AttributeExtensions och ElementExtensions.

Klassen InReplyToElement implementerar IXmlSerializable gränssnittet, vilket ger direkt kontroll över hur objektinstanser läse från och skrivs till XML. Metoden ReadXml läser först värdena för Refegenskaperna , HRef, Sourceoch MediaType från det XmlReader som skickades till den. Alla okända attribut lagras i AttributeExtensions samlingen. När alla attribut har lästs ReadStartElement() anropas för att föra läsaren vidare till nästa element. Eftersom elementet som modelleras av den här klassen inte har några underordnade element som krävs, buffras de underordnade elementen XElement i ElementExtensions instanser och lagras i samlingen, enligt följande kod.

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();
    }
}

Metoden WriteXml först skriver ut värdena för egenskaperna InReplyToElement, Ref, HRef och Source som XML-attribut (MediaType är inte ansvarig för skrivningen av det faktiska yttre elementet, det görs av anroparen av WriteXml). Den skriver också innehållet i AttributeExtensions och ElementExtensions till skrivaren, som du ser i följande kod.

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

I exemplet modelleras SyndicationItems med tilläggen InReplyTo av klassen ThreadedItem. ThreadedFeed På samma sätt är klassen en SyndicationFeed vars objekt är alla instanser av ThreadedItem.

Klassen ThreadedFeed ärver från SyndicationFeed och åsidosätter OnCreateItem för att returnera en ThreadedItem. Den implementerar också en metod för att komma åt samlingen via Items som ThreadedItems, som visas i följande kod.

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

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

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

Klassen ThreadedItem ärver från SyndicationItem och gör InReplyToElement som en starkt typad egenskap. Detta ger praktisk programmatisk åtkomst till tilläggsdata InReplyTo . Den implementerar TryParseElement och WriteElementExtensions för att läsa och skriva tilläggsdata, enligt följande kod.

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);
    }
}

Så här konfigurerar du, skapar och kör exemplet

  1. Kontrollera att du har utfört One-Time installationsproceduren för Windows Communication Foundation-exempel.

  2. Om du vill skapa C# eller Visual Basic .NET-versionen av lösningen följer du anvisningarna i Skapa Windows Communication Foundation-exempel.

  3. Om du vill köra exemplet i en konfiguration med en eller flera datorer följer du anvisningarna i Köra Windows Communication Foundation-exempel.