Voorbeeld van sterk getypte extensies
In het voorbeeld StronglyTypedExtensions wordt de SyndicationFeed klasse gebruikt voor de doeleinden van het voorbeeld. De patronen die in dit voorbeeld worden gedemonstreerd, kunnen echter worden gebruikt met alle syndicatieklassen die extensiegegevens ondersteunen.
Het Syndication-objectmodel (SyndicationFeedSyndicationItemen gerelateerde klassen) ondersteunt losjes getypte toegang tot extensiegegevens met behulp van de AttributeExtensions en ElementExtensions eigenschappen. In dit voorbeeld ziet u hoe u sterk getypte toegang tot extensiegegevens kunt bieden door aangepaste afgeleide klassen van SyndicationFeed te implementeren en SyndicationItem die bepaalde toepassingsspecifieke extensies beschikbaar stellen als sterk getypte eigenschappen.
In dit voorbeeld ziet u hoe u een uitbreidingselement implementeert dat is gedefinieerd in de voorgestelde RFC voor Atom Threading Extensions. Dit is alleen bedoeld voor demonstratiedoeleinden en dit voorbeeld is niet bedoeld als een volledige uitvoering van de voorgestelde specificatie.
Voorbeeld-XML
In het volgende XML-voorbeeld ziet u een Atom 1.0-vermelding met een extra <in-reply-to>
extensie-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>
Met <in-reply-to>
het element worden drie vereiste kenmerken (ref
type
enhref
) opgegeven, terwijl er ook extra uitbreidingskenmerken en extensie-elementen aanwezig zijn.
Het element In-Reply-To modelleren
In dit voorbeeld wordt het <in-reply-to>
element gemodelleerd als CLR die implementeert IXmlSerializable, waardoor het gebruik met de DataContractSerializer. Er worden ook enkele methoden en eigenschappen geïmplementeerd voor toegang tot de gegevens van het element, zoals wordt weergegeven in de volgende voorbeeldcode.
[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; }
}
De InReplyToElement
klasse implementeert eigenschappen voor het vereiste kenmerk (HRef
, MediaType
en ) evenals Source
verzamelingen voor bewaring AttributeExtensions en ElementExtensions.
De InReplyToElement
klasse implementeert de IXmlSerializable interface, waarmee directe controle wordt verkregen over de manier waarop objectexemplaren worden gelezen en naar XML worden geschreven. De ReadXml
methode leest eerst de waarden voor de Ref
, HRef
en Source
MediaType
eigenschappen van de XmlReader doorgegeven waarden. Onbekende kenmerken worden opgeslagen in de AttributeExtensions verzameling. Wanneer alle kenmerken zijn gelezen, ReadStartElement() wordt aangeroepen om de lezer naar het volgende element te gaan. Omdat het element dat door deze klasse is gemodelleerd geen vereiste onderliggende elementen heeft, worden de onderliggende elementen gebufferd in XElement
exemplaren en opgeslagen in de ElementExtensions verzameling, zoals wordt weergegeven in de volgende 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
de methode worden eerst de waarden van de Ref
, HRef
en Source
MediaType
eigenschappen weggeschreven als XML-kenmerken (WriteXml
is niet verantwoordelijk voor het schrijven van het werkelijke buitenste element zelf, zoals gedaan door de aanroeper van WriteXml
).InReplyToElement
Ook wordt de inhoud van de AttributeExtensions en ElementExtensions naar de schrijver geschreven, zoals wordt weergegeven in de volgende 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 en ThreadedItem
In het voorbeeld SyndicationItems
InReplyTo
worden extensies gemodelleerd door de ThreadedItem
klasse. Op dezelfde manier is de ThreadedFeed
klasse een SyndicationFeed
van de items waarvan alle exemplaren zijn ThreadedItem
.
De ThreadedFeed
klasse neemt over van SyndicationFeed
en overschrijft OnCreateItem
om een ThreadedItem
. Het implementeert ook een methode voor toegang tot de Items
verzameling als ThreadedItems
, zoals wordt weergegeven in de volgende code.
public class ThreadedFeed : SyndicationFeed
{
public ThreadedFeed()
{
}
public IEnumerable<ThreadedItem> ThreadedItems
{
get
{
return this.Items.Cast<ThreadedItem>();
}
}
protected override SyndicationItem CreateItem()
{
return new ThreadedItem();
}
}
De klasse ThreadedItem
neemt over van SyndicationItem
en maakt InReplyToElement
deze als een sterk getypte eigenschap. Dit biedt handige programmatische toegang tot de InReplyTo
extensiegegevens. Het implementeert TryParseElement
en WriteElementExtensions
voor het lezen en schrijven van de extensiegegevens, zoals wordt weergegeven in de volgende 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);
}
}
Het voorbeeld instellen, compileren en uitvoeren
Zorg ervoor dat u de eenmalige installatieprocedure voor de Windows Communication Foundation-voorbeelden hebt uitgevoerd.
Als u de C# of Visual Basic .NET-editie van de oplossing wilt bouwen, volgt u de instructies in het bouwen van de Windows Communication Foundation-voorbeelden.
Als u het voorbeeld wilt uitvoeren in een configuratie met één of meerdere computers, volgt u de instructies in Het uitvoeren van de Windows Communication Foundation-voorbeelden.