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
Stellen Sie sicher, dass Sie die Einmaliges Setupverfahren für Windows Communication Foundation-Beispiele ausgeführt haben.
Zum Erstellen der C#- oder Visual Basic .NET-Edition der Projektmappe befolgen Sie die unter Erstellen der Windows Communication Foundation-Beispiele aufgeführten Anweisungen.
Wenn Sie das Beispiel in einer Konfiguration mit einem Computer oder über Computer hinweg ausführen möchten, folgen Sie den unter Running the Windows Communication Foundation Samples aufgeführten Anweisungen.
Hinweis: |
---|
Die Beispiele sind möglicherweise bereits auf dem Computer installiert. Überprüfen Sie das folgende (standardmäßige) Verzeichnis, 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.
<Installationslaufwerk>:\WF_WCF_Samples\WCF\Extensibility\Syndication\StronglyTypedExtensions
|