Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Przykład StronglyTypedExtensions używa SyndicationFeed klasy na potrzeby przykładu. Jednak wzorce przedstawione w tym przykładzie mogą być używane ze wszystkimi klasami Syndication obsługującymi dane rozszerzeń.
Model obiektów Syndication (SyndicationFeed, SyndicationItem, i powiązane klasy) obsługuje luźno typowany dostęp do danych rozszerzeń przy użyciu właściwości AttributeExtensions i ElementExtensions. W tym przykładzie pokazano, jak zapewnić silnie typowany dostęp do danych rozszerzeń przez zaimplementowanie niestandardowych klas pochodnych SyndicationFeed oraz SyndicationItem, udostępniających niektóre rozszerzenia specyficzne dla aplikacji jako silnie typowane właściwości.
Na przykład w tym przykładzie pokazano, jak zaimplementować element rozszerzenia zdefiniowany w proponowanych rozszerzeniach wątkowych Atom RFC. Jest to przeznaczone tylko do celów demonstracyjnych, a ten przykład nie jest przeznaczony do pełnej implementacji proponowanej specyfikacji.
Przykładowy kod XML
Poniższy przykład XML przedstawia wpis Atom 1.0 z dodatkowym <in-reply-to> elementem rozszerzenia.
<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>
Element <in-reply-to> określa trzy wymagane atrybuty (reftypei href), a jednocześnie umożliwia obecność dodatkowych atrybutów rozszerzenia i elementów rozszerzenia.
Modelowanie elementu In-Reply-To
W tym przykładzie element <in-reply-to> jest modelowany jako CLR, który implementuje IXmlSerializable, co umożliwia jego użycie z DataContractSerializer. Implementuje również niektóre metody i właściwości umożliwiające uzyskiwanie dostępu do danych elementu, jak pokazano w poniższym przykładowym kodzie.
[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; }
}
Klasa InReplyToElement implementuje właściwości wymaganego atrybutu (HRef, MediaType, i Source), a także kolekcje do przechowywania AttributeExtensions i ElementExtensions.
Klasa InReplyToElement implementuje IXmlSerializable interfejs, który umożliwia bezpośrednią kontrolę nad sposobem odczytywania wystąpień obiektów i zapisywania ich w języku XML. Metoda ReadXml najpierw odczytuje wartości właściwości Ref, HRef, Source i MediaType z przekazanego XmlReader. Wszystkie nieznane atrybuty są przechowywane w kolekcji AttributeExtensions . Gdy wszystkie atrybuty zostały odczytane, wywoływana jest funkcja ReadStartElement(), aby przejść czytnik do następnego elementu. Ponieważ element modelowany przez tę klasę nie ma wymaganych elementów podrzędnych, elementy podrzędne są buforowane w XElement wystąpieniach i przechowywane w ElementExtensions kolekcji, jak pokazano w poniższym kodzie.
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();
}
}
W metodzie WriteXml, najpierw zapisywane są wartości właściwości InReplyToElement, Ref, HRef i Source jako atrybuty XML (MediaType nie jest odpowiedzialna za pisanie rzeczywistego elementu zewnętrznego, co jest wykonywane przez obiekt wywołujący WriteXml). Zapisuje również zawartość AttributeExtensions i ElementExtensions do pisarza, jak pokazano w poniższym kodzie.
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 i ThreadedItem
W przykładzie klasa SyndicationItems modeluje InReplyTo z rozszerzeniami ThreadedItem. Podobnie, klasa ThreadedFeed to klasa SyndicationFeed, której elementy są wystąpieniami ThreadedItem.
Klasa ThreadedFeed dziedziczy po SyndicationFeed i nadpisuje OnCreateItem w celu zwrócenia ThreadedItem. Implementuje także metodę do dostępu do kolekcji jako Items, jak pokazano w poniższym kodzie.
public class ThreadedFeed : SyndicationFeed
{
public ThreadedFeed()
{
}
public IEnumerable<ThreadedItem> ThreadedItems
{
get
{
return this.Items.Cast<ThreadedItem>();
}
}
protected override SyndicationItem CreateItem()
{
return new ThreadedItem();
}
}
Klasa ThreadedItem dziedziczy po SyndicationItem i ustanawia InReplyToElement jako silnie typizowaną właściwość. Zapewnia to wygodny programowy dostęp do InReplyTo danych rozszerzenia. Implementuje także TryParseElement i WriteElementExtensions do odczytywania i zapisywania danych rozszerzenia, jak pokazano w poniższym kodzie.
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);
}
}
Aby skonfigurować, skompilować i uruchomić przykładowy program
Upewnij się, że wykonano procedurę instalacji One-Time dla przykładów programu Windows Communication Foundation.
Aby skompilować wersję rozwiązania w języku C# lub Visual Basic .NET, postępuj zgodnie z instrukcjami w Kompilowanie przykładów Windows Communication Foundation.
Aby uruchomić przykład w konfiguracji pojedynczej lub między maszynami, postępuj zgodnie z instrukcjami w Uruchamianie przykładów programu Windows Communication Foundation.