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, SyndicationItemoch relaterade klasser) stöder löst skriven åtkomst till tilläggsdata med hjälp AttributeExtensions av egenskaperna och ElementExtensions . Det här exemplet visar hur du ger starkt skrivskyddad å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 inskrivna 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 (ref
type
och href
) samtidigt som det möjliggör förekomst av ytterligare tilläggsattribut och tilläggselement.
Modellera elementet Svar till
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 Ref
egenskaperna , HRef
, Source
och 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 ElementExtensions i XElement
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();
}
}
I WriteXml
skriver metoden först ut värdena Ref
för egenskaperna , HRef
, Source
och MediaType
som XML-attribut (WriteXml
ansvarar inte för att skriva själva det faktiska yttre elementet, som det som görs av anroparen av WriteXml
).InReplyToElement
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 SyndicationItems
modelleras med InReplyTo
tillägg av ThreadedItem
klassen. 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 Items
komma åt samlingen 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
Kontrollera att du har utfört engångsinstallationsproceduren för Windows Communication Foundation-exempel.
Om du vill skapa C# eller Visual Basic .NET-versionen av lösningen följer du anvisningarna i Skapa Windows Communication Foundation-exempel.
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.