Sampel ekstensi strongly-typed
Sampel StronglyTypedExtensions menggunakan kelas SyndicationFeed untuk tujuan contoh. Namun, pola yang ditunjukkan dalam sampel ini dapat digunakan dengan semua kelas Sindikasi yang mendukung data ekstensi.
Model objek Sindikasi (SyndicationFeed, SyndicationItem, dan kelas terkait) menunjukkan akses loosely-typed ke data ekstensi menggunakan properti AttributeExtensions dan ElementExtensions. Sampel ini menunjukkan cara memberikan akses strongly-typed ke data ekstensi dengan mengimplementasikan kelas turunan kustom SyndicationFeed dan SyndicationItem yang menyediakan ekstensi khusus aplikasi tertentu sebagai properti strongly-typed.
Sebagai contoh, sampel ini menunjukkan cara mengimplementasikan elemen ekstensi yang ditentukan dalam RFC Ekstensi Threading Atom yang diusulkan. Ini hanya untuk tujuan demonstrasi dan sampel ini tidak dimaksudkan untuk menjadi implementasi penuh dari spesifikasi yang diusulkan.
XML Sampel
Contoh XML berikut menunjukkan entri Atom 1.0 dengan elemen ekstensi <in-reply-to>
tambahan.
<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>
Elemen <in-reply-to>
menentukan tiga atribut yang diperlukan (ref
, type
, dan href
) sekaligus memungkinkan keberadaan atribut ekstensi dan elemen ekstensi tambahan.
Memodelkan elemen In-Reply-To
Dalam sampel ini, elemen <in-reply-to>
dimodelkan sebagai CLR yang mengimplementasikan IXmlSerializable, yang memungkinkan penggunaannya dengan DataContractSerializer. Hal ini juga mengimplementasikan beberapa metode dan properti untuk mengakses data elemen, seperti yang ditunjukkan dalam kode sampel berikut.
[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; }
}
Kelas InReplyToElement
mengimplementasikan properti untuk atribut yang diperlukan (HRef
, MediaType
, dan Source
) serta koleksi untuk menyimpan AttributeExtensions dan ElementExtensions.
Kelas InReplyToElement
mengimplementasikan antarmuka IXmlSerializable, yang memungkinkan kontrol langsung atas cara instans objek dibaca dari dan ditulis ke XML. Metode ReadXml
terlebih dahulu membaca nilai untuk properti Ref
, HRef
, Source
, dan MediaType
dari XmlReader yang diteruskan ke dalamnya. Atribut yang tidak diketahui disimpan dalam koleksi AttributeExtensions. Setelah semua atribut dibaca, ReadStartElement() dipanggil untuk mendorong pembaca ke elemen berikutnya. Karena elemen yang dimodelkan oleh kelas ini tidak memiliki turunan yang diperlukan, elemen turunan di-buffer ke dalam instans XElement
dan disimpan dalam koleksi ElementExtensions, seperti yang ditampilkan dalam kode berikut.
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();
}
}
Dalam WriteXml
, metode InReplyToElement
terlebih dahulu menulis nilai untuk properti Ref
, HRef
, Source
, dan MediaType
sebagai atribut XML (WriteXml
tidak bertanggung jawab untuk menulis elemen luar yang aktual sendiri, seperti yang dilakukan oleh pemanggil WriteXml
). Metode ini juga menulis konten AttributeExtensions dan ElementExtensions ke penulis, seperti yang ditampilkan dalam kode berikut.
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 dan ThreadedItem
Pada sampel, SyndicationItems
dengan InReplyTo
ekstensi dimodelkan oleh kelas ThreadedItem
. Demikian pula, kelas ThreadedFeed
adalah SyndicationFeed
yang itemnya merupakan semua instans dari ThreadedItem
.
Kelas ThreadedFeed
mewarisi dari SyndicationFeed
dan mengambil alih OnCreateItem
untuk mengembalikan ThreadedItem
. Hal ini juga mengimplementasikan metode untuk mengakses koleksi Items
sebagai ThreadedItems
, seperti yang ditunjukkan pada kode berikut.
public class ThreadedFeed : SyndicationFeed
{
public ThreadedFeed()
{
}
public IEnumerable<ThreadedItem> ThreadedItems
{
get
{
return this.Items.Cast<ThreadedItem>();
}
}
protected override SyndicationItem CreateItem()
{
return new ThreadedItem();
}
}
Kelas ThreadedItem
mewarisi dari SyndicationItem
dan menjadikan InReplyToElement
sebagai properti strongly-typed. Ini menyediakan akses terprogram yang mudah ke data ekstensi InReplyTo
. Hal tersebut juga mengimplementasikan TryParseElement
dan WriteElementExtensions
untuk membaca dan menulis data ekstensinya, seperti yang ditunjukkan pada kode berikut.
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);
}
}
Untuk menyiapkan, membangun, dan menjalankan sampel
Pastikan Anda telah melakukan Prosedur Penyiapan Satu Kali untuk Sampel Windows Communication Foundation.
Untuk membangun solusi edisi C# atau Visual Basic .NET, ikuti petunjuknya di Membangun Sampel WCF.
Untuk menjalankan sampel dalam konfigurasi satu atau lintas komputer, ikuti instruksi pada Menjalankan Sampel WCF.