Az üzenetosztály használata
Az Message osztály alapvető fontosságú a Windows Communication Foundation (WCF) számára. Az ügyfelek és szolgáltatások közötti kommunikáció végső soron a példányok küldését és fogadását eredményezi Message .
Általában nem lép kapcsolatba közvetlenül az Message osztálysal. Ehelyett a WCF szolgáltatásmodell-szerkezetek, például az adatszerződések, az üzenetszerződések és a műveleti szerződések a bejövő és kimenő üzenetek leírására szolgálnak. Bizonyos speciális helyzetekben azonban közvetlenül az Message osztály használatával programozott. Használhatja például az osztályt Message :
Ha a kimenő üzenetek tartalmának létrehozására (például közvetlenül egy lemezen lévő fájlból) van szüksége egy másik módszerre ahelyett, hogy .NET-keretrendszer objektumokat szerializál.
Ha a bejövő üzenetek tartalmának alternatív módjára van szüksége (például ha XSLT-átalakítást szeretne alkalmazni a nyers XML-tartalomra), ahelyett, hogy deszerializálna .NET-keretrendszer objektumokba.
Ha az üzeneteket az üzenet tartalmától függetlenül általánosan kell kezelnie (például útválasztó, terheléselosztó vagy közzétételi előfizető rendszer létrehozásakor az üzenetek átirányítása vagy továbbítása során).
Az Message osztály használata előtt ismerkedjen meg a WCF adatátviteli architektúrájával az adatátviteli architektúra áttekintésében.
Az A Message az adatok általános célú tárolója, de kialakítása szorosan követi a SOAP protokollban lévő üzenet kialakítását. A SOAP-hez hasonlóan az üzenetek törzse és fejlécei is vannak. Az üzenet törzse tartalmazza a tényleges hasznos adatokat, míg a fejlécek további elnevezett adattárolókat tartalmaznak. A törzs és a fejlécek olvasására és írására vonatkozó szabályok eltérőek, például a fejlécek mindig pufferelve vannak a memóriában, és tetszőleges sorrendben érhetők el, míg a törzs csak egyszer olvasható és streamelhető. A SOAP használatakor az üzenet törzse általában a SOAP törzsre van leképezve, az üzenetfejlécek pedig a SOAP-fejlécekre vannak leképezve.
Az üzenetosztály használata a műveletekben
Az osztályt Message használhatja egy művelet bemeneti paramétereként, egy művelet visszatérési értékeként vagy mindkettőként. Ha Message egy műveletben bárhol használják, a következő korlátozások érvényesek:
A művelet nem rendelkezhet paraméterekkel vagy
ref
paraméterekkelout
.Egynél
input
több paraméter nem lehet. Ha a paraméter jelen van, üzenetnek vagy üzenetszerződés-típusnak kell lennie.A visszatérési típusnak vagy
void
azMessage
üzenetszerződés típusának kell lennie.
Az alábbi példakód érvényes műveleti szerződést tartalmaz.
[ServiceContract]
public interface IMyService
{
[OperationContract]
Message GetData();
[OperationContract]
void PutData(Message m);
}
<ServiceContract()> _
Public Interface IMyService
<OperationContract()> _
Function GetData() As Message
<OperationContract()> _
Sub PutData(ByVal m As Message)
End Interface
Egyszerű üzenetek létrehozása
Az Message osztály statikus CreateMessage
gyári metódusokat biztosít, amelyekkel alapszintű üzeneteket hozhat létre.
Minden CreateMessage
túlterhelés olyan verzióparamétert MessageVersion használ, amely jelzi az üzenethez használni kívánt SOAP és WS-Addressing verziókat. Ha ugyanazokat a protokollverziókat szeretné használni, mint a bejövő üzenet, használhatja a IncomingMessageVersion tulajdonságból beszerzett példány tulajdonságát OperationContext Current . A legtöbb CreateMessage
túlterhelésnek van egy sztringparamétere is, amely az üzenethez használni kívánt SOAP-műveletet jelzi. A verzió beállítható úgy, hogy letiltsa a None
SOAP-borítékok létrehozását. Az üzenet csak a törzsből áll.
Üzenetek létrehozása objektumokból
A legalapvetőbb CreateMessage
túlterhelés, amely csak egy verziót és egy műveletet vesz igénybe, üres törzsű üzenetet hoz létre. Egy másik túlterhelés további Object paramétert vesz igénybe; ez létrehoz egy üzenetet, amelynek törzse az adott objektum szerializált ábrázolása. A szerializáláshoz használja az DataContractSerializer alapértelmezett beállításokat. Ha másik szerializálót szeretne használni, vagy másképpen szeretné konfigurálni, DataContractSerializer
használja azt a CreateMessage
túlterhelést, amely egy paramétert XmlObjectSerializer
is használ.
Ha például egy objektumot szeretne visszaadni egy üzenetben, használhatja az alábbi kódot.
public class MyService1 : IMyService
{
public Message GetData()
{
Person p = new Person();
p.name = "John Doe";
p.age = 42;
MessageVersion ver = OperationContext.Current.IncomingMessageVersion;
return Message.CreateMessage(ver, "GetDataResponse", p);
}
public void PutData(Message m)
{
// Not implemented.
}
}
[DataContract]
public class Person
{
[DataMember] public string name;
[DataMember] public int age;
}
Public Class MyService1
Implements IMyService
Public Function GetData() As Message _
Implements IMyService.GetData
Dim p As New Person()
p.name = "John Doe"
p.age = 42
Dim ver As MessageVersion = _
OperationContext.Current.IncomingMessageVersion
Return Message.CreateMessage(ver, "GetDataResponse", p)
End Function
Public Sub PutData(ByVal m As Message) _
Implements IMyService.PutData
' Not implemented.
End Sub
End Class
<DataContract()> _
Public Class Person
<DataMember()> _
Public name As String
<DataMember()> _
Public age As Integer
End Class
Üzenetek létrehozása XML-olvasókból
Vannak CreateMessage
olyan túlterhelések, amelyek egy objektum helyett egy XmlReader vagy egy XmlDictionaryReader testet vesznek igénybe. Ebben az esetben az üzenet törzse tartalmazza azt az XML-t, amely az átadott XML-olvasóból való olvasásból származik. Az alábbi kód például egy XML-fájlból beolvasott törzstartalommal rendelkező üzenetet ad vissza.
public class MyService2 : IMyService
{
public Message GetData()
{
FileStream stream = new FileStream("myfile.xml",FileMode.Open);
XmlDictionaryReader xdr =
XmlDictionaryReader.CreateTextReader(stream,
new XmlDictionaryReaderQuotas());
MessageVersion ver =
OperationContext.Current.IncomingMessageVersion;
return Message.CreateMessage(ver,"GetDataResponse",xdr);
}
public void PutData(Message m)
{
// Not implemented.
}
}
Public Class MyService2
Implements IMyService
Public Function GetData() As Message Implements IMyService.GetData
Dim stream As New FileStream("myfile.xml", FileMode.Open)
Dim xdr As XmlDictionaryReader = _
XmlDictionaryReader.CreateTextReader(stream, New XmlDictionaryReaderQuotas())
Dim ver As MessageVersion = OperationContext.Current.IncomingMessageVersion
Return Message.CreateMessage(ver, "GetDataResponse", xdr)
End Function
Public Sub PutData(ByVal m As Message) Implements IMyService.PutData
End Sub
End Class
Emellett vannak CreateMessage
túlterhelések, amelyek a XmlReader XmlDictionaryReader teljes üzenetet és nem csak a törzset jelölik. Ezek a túlterhelések egész paramétert maxSizeOfHeaders
is vesznek igénybe. A fejlécek mindig pufferelve lesznek a memóriába az üzenet létrehozása után, és ez a paraméter korlátozza a pufferelés mennyiségét. Fontos, hogy ezt a paramétert biztonságos értékre állítsa, ha az XML nem megbízható forrásból származik, hogy mérsékelje a szolgáltatásmegtagadásos támadás lehetőségét. Az XML-olvasó által képviselt üzenet SOAP és WS-Addressing verzióinak meg kell egyezniük a verzióparaméterrel jelzett verziókkal.
Üzenetek létrehozása a BodyWriter használatával
Egy CreateMessage
túlterhelés egy BodyWriter
példányt vesz igénybe az üzenet törzsének leírásához. Az A BodyWriter
egy absztrakt osztály, amely az üzenettörzsek létrehozásának testreszabására használható. Létrehozhat saját BodyWriter
származtatott osztályt az üzenettörzsek egyéni leírásához. Felül kell bírálnia a BodyWriter.OnWriteBodyContents
metódust XmlDictionaryWriter, amely egy ; ez a módszer felelős a törzs írásáért.
A törzsírók pufferelhetők vagy nem pufferelhetők (streamelhetők). A pufferelt szövegtörzs-írók tetszőleges számú alkalommal írhatják ki a tartalmukat, míg a streameltek csak egyszer írhatják ki a tartalmukat. A IsBuffered
tulajdonság azt jelzi, hogy a szövegtörzs-író pufferelt-e vagy sem. Ezt a törzsíróhoz úgy állíthatja be, hogy meghívja a logikai paramétert használó védett BodyWriter
konstruktort isBuffered
. A testírók támogatják a pufferelt testírók létrehozását nem pufferelt testírókból. A folyamat testreszabásához felülbírálhatja a OnCreateBufferedCopy
metódust. Alapértelmezés szerint a rendszer egy memóriabeli puffert használ, amely a visszaadott OnWriteBodyContents
XML-t tartalmazza. OnCreateBufferedCopy
egész szám paramétert maxBufferSize
használ; ha felülbírálja ezt a módszert, nem szabad ennél nagyobb puffereket létrehoznia.
Az BodyWriter
osztály biztosítja azokat a WriteBodyContents
metódusokat és CreateBufferedCopy
metódusokat, amelyek lényegében vékony burkolók OnWriteBodyContents
és OnCreateBufferedCopy
metódusok. Ezek a metódusok állapotellenőrzést végeznek annak érdekében, hogy a nem pufferelt szövegtörzs-írók ne férhessenek hozzá többször. Ezeket a metódusokat közvetlenül csak akkor hívjuk meg, ha egyéni Message
származtatott osztályokat hozunk létre az alapján BodyWriters
.
Hibaüzenetek létrehozása
Bizonyos CreateMessage
túlterhelések használatával SOAP-hibaüzeneteket hozhat létre. Ezek közül a legalapvetőbb a MessageFault hibát leíró objektum. Más túlterhelések is biztosítottak a kényelem érdekében. Az első ilyen túlterhelés egy és egy ok sztringet FaultCode
vesz igénybe, és létrehoz egy MessageFault
ilyen MessageFault.CreateFault
információt használó karakterláncot. A másik túlterhelés egy részletes objektumot vesz igénybe, és a hibakóddal és az okokkal együtt továbbítja CreateFault
azt. Az alábbi művelet például hibát ad vissza.
public class MyService3 : IMyService
{
public Message GetData()
{
FaultCode fc = new FaultCode("Receiver");
MessageVersion ver = OperationContext.Current.IncomingMessageVersion;
return Message.CreateMessage(ver,fc,"Bad data","GetDataResponse");
}
public void PutData(Message m)
{
// Not implemented.
}
}
Public Class MyService3
Implements IMyService
Public Function GetData() As Message Implements IMyService.GetData
Dim fc As New FaultCode("Receiver")
Dim ver As MessageVersion = OperationContext.Current.IncomingMessageVersion
Return Message.CreateMessage(ver, fc, "Bad data", "GetDataResponse")
End Function
Public Sub PutData(ByVal m As Message) Implements IMyService.PutData
End Sub
End Class
Üzenettörzs adatainak kinyerése
Az Message
osztály többféle módon is képes kinyerni az információkat a törzséből. Ezek a következő kategóriákba sorolhatók be:
A teljes üzenettörzset egyszerre kell kiírnia egy XML-írónak. Ezt üzenet írásának nevezzük.
XML-olvasó lekérése az üzenet törzsén. Ez lehetővé teszi, hogy később szükség szerint, darabonként hozzáférjen az üzenet törzséhez. Ezt üzenet olvasásának nevezzük.
A teljes üzenet, beleértve a törzsét is, átmásolható egy MessageBuffer ilyen típusú memóriabeli pufferbe. Ezt nevezzük üzenet másolásának.
A törzs Message
csak egyszer érhető el, függetlenül attól, hogy hogyan érhető el. Az üzenetobjektumok State
tulajdonsága kezdetben Létrehozás értékre van állítva. Az előző listában ismertetett három hozzáférési módszer írási, olvasási és másolási állapotot állít be. Emellett egy Close
metódus akkor is bezárt állapotba állíthatja az állapotot, ha már nincs szükség az üzenet törzsének tartalmára. Az üzenet törzse csak a Létrehozott állapotban érhető el, és az állapot módosítása után nem lehet visszamenni a Létrehozott állapotba.
Üzenetek írása
A WriteBodyContents(XmlDictionaryWriter) metódus egy adott Message
példány törzstartalmat ír ki egy adott XML-írónak. A WriteBody módszer ugyanezt teszi, azzal a kivételsel, hogy a törzs tartalmát a megfelelő burkolóelembe (például <soap:body>
) csomagolja. WriteMessage Végül írja ki a teljes üzenetet, beleértve a burkoló SOAP borítékot és a fejléceket. Ha a SOAP ki van kapcsolva (Version is MessageVersion.None), mindhárom módszer ugyanezt teszi: kiírják az üzenet törzsének tartalmát.
Az alábbi kód például egy bejövő üzenet törzsét írja ki egy fájlba.
public class MyService4 : IMyService
{
public void PutData(Message m)
{
FileStream stream = new FileStream("myfile.xml",FileMode.Create);
XmlDictionaryWriter xdw =
XmlDictionaryWriter.CreateTextWriter(stream);
m.WriteBodyContents(xdw);
xdw.Flush();
}
public Message GetData()
{
throw new NotImplementedException();
}
}
Public Class MyService4
Implements IMyService
Public Sub PutData(ByVal m As Message) Implements IMyService.PutData
Dim stream As New FileStream("myfile.xml", FileMode.Create)
Dim xdw As XmlDictionaryWriter = XmlDictionaryWriter.CreateTextWriter(stream)
m.WriteBodyContents(xdw)
xdw.Flush()
End Sub
Public Function GetData() As Message Implements IMyService.GetData
Throw New NotImplementedException()
End Function
End Class
Két további segítő módszer ír ki bizonyos SOAP kezdőelem-címkéket. Ezek a metódusok nem férnek hozzá az üzenet törzséhez, ezért nem módosítják az üzenet állapotát. Ezek közé tartoznak:
WriteStartBody Írja például a kezdő törzselemet
<soap:Body>
.WriteStartEnvelope írja a kezdő boríték elemet, például
<soap:Envelope>
.
A megfelelő záróelemcímkék írásához hívja meg WriteEndElement
a megfelelő XML-írót. Ezeket a metódusokat ritkán nevezik közvetlenül.
Üzenetek olvasása
Az üzenettörzs olvasásának elsődleges módja a hívás GetReaderAtBodyContents. Egy olyan üzenetet kap vissza XmlDictionaryReader , amellyel elolvashatja az üzenet törzsét. Vegye figyelembe, hogy az Message áttűnés az olvasási állapotra a hívás után azonnal GetReaderAtBodyContents történik, és nem a visszaadott XML-olvasó használatakor.
A GetBody metódus lehetővé teszi az üzenet törzsének gépelt objektumként való elérését is. Ez a metódus belsőleg használja GetReaderAtBodyContents
, így az üzenet állapotát is áttűni az Read állapotra (lásd a tulajdonságot State ).
Érdemes ellenőrizni a IsEmpty tulajdonságot, ebben az esetben az üzenettörzs üres, és GetReaderAtBodyContents dob egy InvalidOperationException. Ha ez egy fogadott üzenet (például a válasz), érdemes lehet ellenőrizni IsFaultis, amely jelzi, hogy az üzenet tartalmaz-e hibát.
A deszerializálás legalapvetőbb túlterhelése GetBody egy (az általános paraméter által jelzett) DataContractSerializer típuspéldányba alakítja az üzenettörzset az alapértelmezett beállításokkal konfigurált és a MaxItemsInObjectGraph kvóta letiltásával. Ha másik szerializációs motort szeretne használni, vagy nem alapértelmezett módon szeretné konfigurálni, DataContractSerializer
használja a GetBody túlterhelést, amely egy XmlObjectSerializer.
Az alábbi kód például adatokat nyer ki egy szerializált Person
objektumot tartalmazó üzenettörzsből, és kinyomtatja a személy nevét.
public class MyService5 : IMyService
{
public void PutData(Message m)
{
Person p = m.GetBody<Person>();
Console.WriteLine(p.name);
}
public Message GetData()
{
throw new NotImplementedException();
}
}
}
namespace Samples2
{
[ServiceContract]
public interface IMyService
{
[OperationContract]
Message GetData();
[OperationContract]
void PutData(Message m);
}
[DataContract]
public class Person
{
[DataMember] public string name;
[DataMember] public int age;
}
Public Class MyService5
Implements IMyService
Public Sub PutData(ByVal m As Message) Implements IMyService.PutData
Dim p As Person = m.GetBody(Of Person)()
Console.WriteLine(p.name)
End Sub
Public Function GetData() As Message Implements IMyService.GetData
Throw New NotImplementedException()
End Function
End Class
End Namespace
Namespace Samples2
<ServiceContract()> _
Public Interface IMyService
<OperationContract()> _
Function GetData() As Message
<OperationContract()> _
Sub PutData(ByVal m As Message)
End Interface
<DataContract()> _
Public Class Person
<DataMember()> _
Public name As String
<DataMember()> _
Public age As Integer
End Class
Üzenet másolása pufferbe
Előfordulhat, hogy többször is hozzá kell férni az üzenet törzséhez, például egy közzétevő-előfizető rendszer részeként ugyanazt az üzenetet több célhelyre kell továbbítani. Ebben az esetben a teljes üzenetet (beleértve a törzset) pufferelni kell a memóriában. Ezt a hívással CreateBufferedCopy(Int32)teheti meg. Ez a metódus egy egész szám paramétert használ, amely a maximális pufferméretet jelöli, és létrehoz egy olyan puffert, amely nem nagyobb ennél a méretnél. Fontos, hogy ezt biztonságos értékre állítsa, ha az üzenet nem megbízható forrásból származik.
A puffer példányként lesz visszaadva MessageBuffer . A pufferben lévő adatokat többféleképpen is elérheti. Az elsődleges módszer a CreateMessage példányok pufferből való létrehozása Message
.
A pufferben lévő adatok elérésének másik módja az osztály által MessageBuffer implementálható felület implementálása IXPathNavigable az alapul szolgáló XML közvetlen eléréséhez. Egyes CreateNavigator túlterhelések lehetővé teszik a csomópontkvóta által védett kezelők létrehozását System.Xml.XPath , korlátozva a látogatható XML-csomópontok számát. Ez segít megelőzni a szolgáltatásmegtagadási támadásokat a hosszú feldolgozási idő alapján. Ez az ajánlat alapértelmezés szerint le van tiltva. Egyes CreateNavigator
túlterhelések lehetővé teszik, hogy megadhatja, hogyan kell kezelni a szabad területet az XML-ben az XmlSpace enumerálás használatával, az alapértelmezett érték pedig XmlSpace.None
a .
Az üzenetpuffer tartalmának elérésének végső módja az, ha a tartalmát egy streambe írja ki a használatával WriteMessage.
Az alábbi példa bemutatja, hogy a MessageBuffer
rendszer egy bejövő üzenetet több címzettnek továbbít, majd egy fájlba naplóz. Pufferelés nélkül ez nem lehetséges, mert az üzenet törzse csak egyszer érhető el.
[ServiceContract]
public class ForwardingService
{
private List<IOutputChannel> forwardingAddresses;
[OperationContract]
public void ForwardMessage (Message m)
{
//Copy the message to a buffer.
MessageBuffer mb = m.CreateBufferedCopy(65536);
//Forward to multiple recipients.
foreach (IOutputChannel channel in forwardingAddresses)
{
Message copy = mb.CreateMessage();
channel.Send(copy);
}
//Log to a file.
FileStream stream = new FileStream("log.xml",FileMode.Append);
mb.WriteMessage(stream);
stream.Flush();
}
}
<ServiceContract()> _
Public Class ForwardingService
Private forwardingAddresses As List(Of IOutputChannel)
<OperationContract()> _
Public Sub ForwardMessage(ByVal m As Message)
'Copy the message to a buffer.
Dim mb As MessageBuffer = m.CreateBufferedCopy(65536)
'Forward to multiple recipients.
Dim channel As IOutputChannel
For Each channel In forwardingAddresses
Dim copy As Message = mb.CreateMessage()
channel.Send(copy)
Next channel
'Log to a file.
Dim stream As New FileStream("log.xml", FileMode.Append)
mb.WriteMessage(stream)
stream.Flush()
End Sub
End Class
Az MessageBuffer
osztálynak más tagjai is vannak, érdemes megjegyezni. A Close metódus meghívható erőforrások felszabadítására, ha már nincs szükség a puffer tartalmára. A BufferSize tulajdonság a lefoglalt puffer méretét adja vissza. A MessageContentType tulajdonság az üzenet MIME-tartalomtípusát adja vissza.
Az üzenettörzs elérése hibakereséshez
Hibakeresés céljából meghívhatja a metódust, ToString hogy sztringként ábrázolja az üzenetet. Ez az ábrázolás általában megegyezik azzal, ahogyan egy üzenet a vezetéken nézne, ha a szövegkódolóval lenne kódolva, azzal a kivétellel, hogy az XML jobban formázható lenne az emberi olvashatóság érdekében. Ez alól az egyetlen kivétel az üzenet törzse. A törzs csak egyszer olvasható, és ToString
nem módosítja az üzenet állapotát. Ezért előfordulhat, hogy a ToString
metódus nem fér hozzá a törzshez, és helyettesítheti a helyőrzőt (például "..." vagy három pont) az üzenet törzse helyett. Ezért ne használja ToString
az üzenetek naplózását, ha az üzenetek törzstartalma fontos.
Egyéb üzenetrészek elérése
A rendszer különböző tulajdonságokat biztosít az üzenet információinak eléréséhez a törzs tartalmától eltérően. Ezek azonban nem hívhatók meg az üzenet bezárása után:
A Headers tulajdonság az üzenetfejléceket jelöli. A témakör későbbi részében a "Fejlécek használata" című szakaszt tekinti meg.
A Properties tulajdonság az üzenet tulajdonságait jelöli, amelyek az üzenethez csatolt elnevezett adatok, amelyek általában nem lesznek kibocsátva az üzenet elküldésekor. Tekintse meg a témakör későbbi részében a "Tulajdonságok használata" című szakaszt.
A Version tulajdonság az üzenethez társított SOAP és WS-Addressing verziót jelzi, vagy
None
ha a SOAP le van tiltva.A IsFault tulajdonság akkor ad
true
vissza, ha az üzenet SOAP-hibaüzenet.A IsEmpty tulajdonság akkor ad
true
vissza, ha az üzenet üres.
A metódussal GetBodyAttribute(String, String) hozzáférhet egy adott névvel és névtérrel azonosított törzsburkoló elemhez (például <soap:Body>
) egy adott attribútumhoz. Ha nem található ilyen attribútum, null
a rendszer visszaadja. Ez a metódus csak akkor hívható meg, ha a Message
rendszer a Létrehozott állapotban van (ha az üzenet törzse még nem érhető el).
Élőfejek használata
Az A Message
tetszőleges számú elnevezett XML-szilánkot, úgynevezett fejlécet tartalmazhat. Minden töredék általában soap fejlécre van leképezett állapotban. A fejlécek a Headers
típus MessageHeaderstulajdonságán keresztül érhetők el. MessageHeaders objektumgyűjtemény MessageHeaderInfo , és az egyes fejlécek a felületén IEnumerable vagy az indexelőn keresztül érhetők el. Az alábbi kód például a fejlécek nevét sorolja fel.Message
public class MyService6 : IMyService
{
public void PutData(Message m)
{
foreach (MessageHeaderInfo mhi in m.Headers)
{
Console.WriteLine(mhi.Name);
}
}
public Message GetData()
{
throw new NotImplementedException();
}
}
Public Class MyService6
Implements IMyService
Public Sub PutData(ByVal m As Message) Implements IMyService.PutData
Dim mhi As MessageHeaderInfo
For Each mhi In m.Headers
Console.WriteLine(mhi.Name)
Next mhi
End Sub
Public Function GetData() As Message Implements IMyService.GetData
Throw New NotImplementedException()
End Function
End Class
Élőfejek hozzáadása, eltávolítása, keresése
A metódussal Add új fejlécet adhat hozzá az összes meglévő fejléc végéhez. A metódussal Insert beszúrhat egy fejlécet egy adott indexbe. A program áthelyezi a meglévő fejléceket a beszúrt elemhez. A fejlécek az indexük szerint vannak rendezve, az első elérhető index pedig a 0. A különböző CopyHeadersFrom metódustúlterheltségekkel fejléceket vehet fel egy másik Message
vagy MessageHeaders
példányból. Egyes túlterhelések egyetlen élőfejet másolnak, míg mások mindegyiket másolják. A Clear metódus eltávolítja az összes fejlécet. A RemoveAt metódus eltávolít egy fejlécet egy adott indexen (az összes fejlécet eltolja utána). A RemoveAll metódus eltávolítja az adott névvel és névtérrel rendelkező összes fejlécet.
Egy adott fejléc lekérése a FindHeader módszerrel. Ez a metódus a fejléc nevét és névterét keresi, és visszaadja annak indexét. Ha a fejléc többször is előfordul, a rendszer kivételt jelez. Ha a fejléc nem található, az -1 értéket adja vissza.
A SOAP-fejlécmodellben az élőfejek olyan értékkel rendelkezhetnek Actor
, amely meghatározza a fejléc kívánt címzettjének nevét. A legalapvetőbb FindHeader
túlterhelés csak az üzenet végső címzettjének szánt fejléceket keresi. Egy másik túlterhelés azonban lehetővé teszi annak megadását, hogy mely Actor
értékek szerepelnek a keresésben. További információkért lásd a SOAP specifikációját.
A CopyTo(MessageHeaderInfo[], Int32) rendszer metódust biztosít az élőfejek gyűjteményből MessageHeaders egy objektumtömbbe való másolásához MessageHeaderInfo .
Az XML-adatok fejlécben való eléréséhez meghívhat GetReaderAtHeader és visszaadhat egy XML-olvasót az adott fejlécindexhez. Ha a fejléc tartalmát objektummá szeretné deszerializálni, használja GetHeader<T>(Int32) vagy a többi túlterhelés egyikét. A legalapvetőbb túlterhelések az alapértelmezett módon konfigurált módon deszerializálják a fejléceket DataContractSerializer . Ha másik szerializálót vagy más konfigurációt DataContractSerializer
szeretne használni, használja az egyik túlterhelést, amely egy XmlObjectSerializer
. Vannak túlterhelések is, amelyek a fejléc nevét, a névteret és opcionálisan az értékek listáját Actor
használják index helyett; ez a kombináció FindHeader
és GetHeader
a .
Tulajdonságok használata
A Message
példányok tetszőleges számú tetszőleges típusú elnevezett objektumot tartalmazhatnak. Ez a gyűjtemény a Properties
típustulajdonságon MessageProperties
keresztül érhető el. A gyűjtemény implementálja az IDictionary<TKey,TValue> interfészt, és leképezésként működik.ObjectString A tulajdonságértékek általában nem képezhetők közvetlenül a vezetéken lévő üzenet egyik részéhez sem, hanem különböző üzenetfeldolgozási tippeket nyújtanak a WCF-csatorna verem különböző csatornáihoz vagy a CopyTo(MessageHeaderInfo[], Int32) szolgáltatási keretrendszerhez. Példa: Adatátviteli architektúra áttekintése.
Öröklődés az üzenetosztályból
Ha a beépített üzenettípusok nem CreateMessage
felelnek meg a követelményeknek, hozzon létre egy osztályt, amely az Message
osztályból származik.
Az üzenettörzs tartalmának meghatározása
Az üzenettörzsben lévő adatok eléréséhez három elsődleges technika létezik: írás, olvasás és másolás egy pufferbe. Ezek a műveletek végül azt eredményezik, OnGetReaderAtBodyContentshogy a OnWriteBodyContentsmetódusok neve OnCreateBufferedCopy a származtatott osztályon Message
lesz. Az alaposztály Message
garantálja, hogy az egyes Message
példányokhoz csak az egyik metódust hívja meg, és hogy a rendszer csak egyszer hívja meg. Az alaposztály azt is biztosítja, hogy a metódusok ne legyenek zárt üzenetben meghívva. Nincs szükség az üzenet állapotának nyomon követésére a megvalósításban.
OnWriteBodyContents absztrakciós módszer, amelyet végre kell hajtani. Az üzenet törzstartalmának meghatározásának legalapvetőbb módja az írás ezzel a módszerrel. Az alábbi üzenet például 100 000 véletlenszerű számot tartalmaz 1 és 20 között.
public class RandomMessage : Message
{
override protected void OnWriteBodyContents(XmlDictionaryWriter writer)
{
Random r = new Random();
for (int i = 0; i <100000; i++)
{
writer.WriteStartElement("number");
writer.WriteValue(r.Next(1,20));
writer.WriteEndElement();
}
}
//code omitted…
Public Class RandomMessage
Inherits Message
Protected Overrides Sub OnWriteBodyContents( _
ByVal writer As XmlDictionaryWriter)
Dim r As New Random()
Dim i As Integer
For i = 0 To 99999
writer.WriteStartElement("number")
writer.WriteValue(r.Next(1, 20))
writer.WriteEndElement()
Next i
End Sub
' Code omitted.
A OnGetReaderAtBodyContents() metódusok és OnCreateBufferedCopy az alapértelmezett implementációk a legtöbb esetben működnek. Az alapértelmezett implementációk meghívják OnWriteBodyContents, pufferelik az eredményeket, és együttműködnek az eredményként kapott pufferrel. Bizonyos esetekben azonban ez nem elegendő. Az előző példában az üzenet olvasása 100 000 XML-elem pufferelését eredményezi, ami nem feltétlenül kívánatos. Érdemes lehet felülbírálni OnGetReaderAtBodyContents() egy egyéni XmlDictionaryReader származtatott osztályt, amely véletlenszerű számokat szolgál ki. Ezt követően felülbírálhatja OnWriteBodyContents a metódus által visszaadott olvasó OnGetReaderAtBodyContents() használatát az alábbi példában látható módon.
public override MessageHeaders Headers
{
get { throw new Exception("The method or operation is not implemented."); }
}
public override MessageProperties Properties
{
get { throw new Exception("The method or operation is not implemented."); }
}
public override MessageVersion Version
{
get { throw new Exception("The method or operation is not implemented."); }
}
}
public class RandomMessage2 : Message
{
override protected XmlDictionaryReader OnGetReaderAtBodyContents()
{
return new RandomNumbersXmlReader();
}
override protected void OnWriteBodyContents(XmlDictionaryWriter writer)
{
XmlDictionaryReader xdr = OnGetReaderAtBodyContents();
writer.WriteNode(xdr, true);
}
public override MessageHeaders Headers
{
get { throw new Exception("The method or operation is not implemented."); }
}
public override MessageProperties Properties
{
get { throw new Exception("The method or operation is not implemented."); }
}
public override MessageVersion Version
{
get { throw new Exception("The method or operation is not implemented."); }
}
}
public class RandomNumbersXmlReader : XmlDictionaryReader
{
//code to serve up 100000 random numbers in XML form omitted…
Public Overrides ReadOnly Property Headers() As MessageHeaders
Get
Throw New Exception("The method or operation is not implemented.")
End Get
End Property
Public Overrides ReadOnly Property Properties() As MessageProperties
Get
Throw New Exception("The method or operation is not implemented.")
End Get
End Property
Public Overrides ReadOnly Property Version() As MessageVersion
Get
Throw New Exception("The method or operation is not implemented.")
End Get
End Property
End Class
Public Class RandomMessage2
Inherits Message
Protected Overrides Function OnGetReaderAtBodyContents() As XmlDictionaryReader
Return New RandomNumbersXmlReader()
End Function
Protected Overrides Sub OnWriteBodyContents(ByVal writer As XmlDictionaryWriter)
Dim xdr As XmlDictionaryReader = OnGetReaderAtBodyContents()
writer.WriteNode(xdr, True)
End Sub
Public Overrides ReadOnly Property Headers() As MessageHeaders
Get
Throw New Exception("The method or operation is not implemented.")
End Get
End Property
Public Overrides ReadOnly Property Properties() As MessageProperties
Get
Throw New Exception("The method or operation is not implemented.")
End Get
End Property
Public Overrides ReadOnly Property Version() As MessageVersion
Get
Throw New Exception("The method or operation is not implemented.")
End Get
End Property
End Class
Public Class RandomNumbersXmlReader
Inherits XmlDictionaryReader
'code to serve up 100000 random numbers in XML form omitted
Hasonlóképpen érdemes lehet felülbírálni OnCreateBufferedCopy
a saját MessageBuffer
származtatott osztály visszaadásához.
Az üzenettörzs tartalmának megadása mellett az üzenet származtatott osztályának felül kell bírálnia a , Headers
és Properties
a Version
tulajdonságokat is.
Vegye figyelembe, hogy ha másolatot készít egy üzenetről, a másolat az eredeti üzenetfejléceket használja.
Egyéb felülírható tagok
Felülbírálhatja a OnWriteStartEnvelopeSOAP-borítékOnWriteStartHeadersOnWriteStartBody, a SOAP-fejlécek és a SOAP törzselem kezdőcímkék írásának módját. Ezek általában a következőknek felelnek meg<soap:Envelope>
: , <soap:Header>
és <soap:Body>
. Ezek a metódusok általában nem írnak ki semmit, ha a Version tulajdonság visszatér None.
Feljegyzés
A hívások OnWriteStartEnvelope
alapértelmezett implementációja, az OnWriteStartBody
eredmények meghívása OnGetReaderAtBodyContents
OnWriteBodyContents
és pufferelése előtt. A fejlécek nincsenek kiírva.
Felülbírálhatja a OnWriteMessage metódust a teljes üzenet különböző részeiből való felépítésének módosításához. A OnWriteMessage
metódus meghívása az alapértelmezett OnCreateBufferedCopy implementációból történikWriteMessage. Vegye figyelembe, hogy a felülírás WriteMessage nem ajánlott eljárás. Jobb, ha felülbírálja a megfelelő On
metódusokat (például OnWriteStartEnvelope, OnWriteStartHeadersés OnWriteBodyContents.
Felülbírálás az üzenettörzs hibakeresés közbeni ábrázolási módjának felülbírálásához OnBodyToString . Az alapértelmezett érték az, hogy három pontként ("...") jeleníti meg. Vegye figyelembe, hogy ezt a metódust többször is meghívhatja, ha az üzenet állapota nem zárt. Ennek a módszernek a megvalósítása soha nem okozhat olyan műveletet, amelyet csak egyszer kell végrehajtani (például csak továbbítási adatfolyamból történő olvasást).
Bírálja felül a metódust OnGetBodyAttribute , hogy engedélyezze az attribútumokhoz való hozzáférést a SOAP törzselemen. Ez a metódus tetszőleges számú alkalommal hívható meg, de az Message
alaptípus garantálja, hogy csak akkor hívják meg, ha az üzenet Létrehozás állapotban van. Nem szükséges ellenőrizni az állapotot egy implementációban. Az alapértelmezett implementáció mindig visszaadja null
az értéket, ami azt jelzi, hogy nincsenek attribútumok a törzselemen.
Ha az Message
objektumnak speciális tisztítást kell végeznie, ha már nincs szükség az üzenettörzsre, felülbírálhatja a parancsot OnClose. Az alapértelmezett implementáció nem végez semmit.
A IsEmpty
tulajdonságok felülírhatók IsFault
. Alapértelmezés szerint mindkettő ad vissza false
.