Jegyzet
Az oldalhoz való hozzáférés engedélyezést igényel. Próbálhatod be jelentkezni vagy könyvtárat váltani.
Az oldalhoz való hozzáférés engedélyezést igényel. Megpróbálhatod a könyvtár váltását.
A tömörítési minta bemutatja, hogyan implementálhat egyéni kódolót a Windows Communication Foundation (WCF) platform használatával.
Minta részletei
Ez a minta egy ügyfélkonzolprogramból (.exe), egy saját üzemeltetésű szolgáltatáskonzolprogramból (.exe) és egy tömörítési üzenetkódoló kódtárból (.dll) áll. A szolgáltatás megvalósít egy szerződést, amely egy kérés-válasz kommunikációs mintát határoz meg. A szerződést az ISampleServer interfész határozza meg, amely biztosítja az alapvető szöveg visszhangzás műveleteket (Echo és BigEcho). Az ügyfél szinkronizált kéréseket küld egy adott művelethez, és a szolgáltatás válaszol az üzenetnek az ügyfélnek való ismételt megismétlésével. Az ügyfél- és szolgáltatástevékenység a konzolablakokban látható. A minta célja, hogy bemutassa, hogyan írhat egyéni kódolót, és hogyan szemléltetheti az üzenetek tömörítésének hatását a vezetéken. A tömörítési üzenetkódolóhoz instrumentálást adhat az üzenet méretének, a feldolgozási időnek vagy mindkettőnek a kiszámításához.
Megjegyzés:
A .NET-keretrendszer 4-ben az automatikus dekompresszió engedélyezve van a WCF kliensen, ha a kiszolgáló tömörített választ küld, amelyet valamilyen algoritmus, például GZip vagy Deflate hozott létre. Ha a szolgáltatás az Internet Information Server (IIS) webszolgáltatása, akkor az IIS konfigurálható úgy, hogy a szolgáltatás tömörített választ küldjön. Ez a minta akkor használható, ha a követelmény a tömörítés és a dekompresszió mind az ügyfélen, mind a szolgáltatáson, vagy ha a szolgáltatás saját üzemeltetésű.
A minta bemutatja, hogyan hozhat létre és integrálhat egyéni üzenetkódolót egy WCF-alkalmazásba. A kódtár GZipEncoder.dll az ügyféllel és a szolgáltatással együtt is üzembe van helyezve. Ez a minta az üzenetek tömörítésének hatását is bemutatja. A GZipEncoder.dll kódja a következőket mutatja be:
Egyéni kódoló és kódológyár létrehozása.
Kötéselem fejlesztése egyéni kódolóhoz.
Egyéni kötési konfiguráció használata egyéni kötéselemek integrálásához.
Egyéni konfigurációkezelő fejlesztése egyéni kötéselemek fájlkonfigurációjának engedélyezéséhez.
Ahogy korábban jeleztük, több réteg is létezik, amelyek egy egyéni kódolóban vannak implementálva. Az egyes rétegek közötti kapcsolat jobb szemléltetéséhez a szolgáltatásindítási események egyszerűsített sorrendje az alábbi listában található:
A kiszolgáló elindul.
A konfigurációs információkat beolvasták.
A szolgáltatáskonfiguráció regisztrálja az egyéni konfigurációkezelőt.
A szolgáltatás hosztja létrejön és megnyílik.
Az egyéni konfigurációs elem létrehozza és visszaadja az egyéni kötési elemet.
Az egyéni kötéselem létrehoz és visszaad egy üzenetkódoló-előállítót.
Üzenet érkezik.
Az üzenetkódoló-előállító egy üzenetkódolót ad vissza az üzenetben való olvasáshoz és a válasz írásához.
A kódoló réteg osztály-előállítóként van implementálva. Az egyéni kódolóhoz csak a kódolóosztály-előállítót szabad nyilvánosan elérhetővé tenni. A gyári objektumot a kötési elem adja vissza, amikor a ServiceHost vagy a ChannelFactory<TChannel> objektum létrejön. Az üzenetkódolók pufferelt vagy streamelési módban is működhetnek. Ez a minta a pufferelt és a streamelési módot is bemutatja.
Minden módhoz tartozik egy kísérő metódus: ReadMessage és WriteMessage az absztrakt MessageEncoder osztályban. A kódolási munka nagy része ezekben a metódusokban történik. A minta bevonja a meglévő szöveg- és bináris üzenetkódolókat. Ez lehetővé teszi, hogy a minta delegálja az üzenetek vezetékes ábrázolásának olvasását és írását a belső kódolónak, valamint azt is, hogy a tömörítési kódoló tömörítse vagy kitömörítse az eredményeket. Mivel nincs folyamat az üzenetkódoláshoz, ez az egyetlen modell, amely több kódolót használ a WCF-ben. Az üzenet kibontása után az eredményként kapott üzenet átkerül a csatorna verem kezelésére szolgáló verembe. A tömörítés során az eredményül kapott tömörített üzenet közvetlenül a megadott streambe lesz írva.
Ez a minta segédmetórákat (CompressBuffer és DecompressBuffer) használ a pufferekből streamekké való átalakítás végrehajtásához az GZipStream osztály használatához.
A pufferelt ReadMessage és WriteMessage az osztályok használják az osztályt BufferManager . A kódoló csak a kódoló-előállítón keresztül érhető el. Az absztrakt MessageEncoderFactory osztály egy tulajdonságot biztosít, amely az aktuális kódoló elérésére szolgál Encoder , valamint egy munkameneteket támogató kódoló létrehozására szolgáló CreateSessionEncoder metódust. Ez a kódoló abban a forgatókönyvben használható, amikor a csatorna támogatja a munkameneteket, rendezett és megbízható. Ez a forgatókönyv lehetővé teszi az optimalizálást a vezetékre írt adatok minden egyes munkamenetében. Ha ez nem kívánatos, az alapmetódus nem terhelhető túl. A Encoder tulajdonság egy mechanizmust biztosít a munkamenet nélküli kódoló eléréséhez, és a CreateSessionEncoder metódus alapértelmezett implementációja a tulajdonság értékét adja vissza. Mivel a minta egy meglévő kódolót csomagol a tömörítéshez, az MessageEncoderFactory implementáció elfogadja a MessageEncoderFactory-et, ami a belső kódoló gyárat képviseli.
Most, hogy a kódoló és a kódológyár definiálva van, WCF-ügyféllel és szolgáltatással is használhatók. Azonban ezeket a kódolókat hozzá kell adni a csatornaköteghez. A ServiceHost és ChannelFactory<TChannel> osztályokból származtathat osztályokat, és felülbírálhatja a OnInitialize metódusokat a kódoló-gyár manuális hozzáadásához. A kódoló gyárat egyedi kötési elemen keresztül is elérhetővé teheti.
Új egyéni kötéselem létrehozásához hozzon létre egy osztályt az BindingElement osztályból. A kötési elemeknek azonban számos típusa van. Annak biztosításához, hogy az egyéni kötéselem üzenetkódoló kötéselemként legyen felismerve, azt is meg kell valósítania, hogy a MessageEncodingBindingElement. Ez MessageEncodingBindingElement egy új üzenetkódoló-előállító (CreateMessageEncoderFactory) létrehozására szolgáló metódust tesz elérhetővé, amely a megfelelő üzenetkódoló-előállító egy példányát adja vissza. Emellett a MessageEncodingBindingElement címzési verziót jelző tulajdonság is rendelkezik. Mivel ez a minta integrálja a meglévő kódolókat, a mintafelépítés a meglévő kódoló kötési elemeit is integrálja, és egy belső kódoló kötési elemet vesz fel paraméterként a konstruktorban, amelyet egy tulajdonságon keresztül tesz hozzáférhetővé. Az alábbi mintakód az osztály implementációját GZipMessageEncodingBindingElement mutatja be.
public sealed class GZipMessageEncodingBindingElement
: MessageEncodingBindingElement //BindingElement
, IPolicyExportExtension
{
//We use an inner binding element to store information
//required for the inner encoder.
MessageEncodingBindingElement innerBindingElement;
//By default, use the default text encoder as the inner encoder.
public GZipMessageEncodingBindingElement()
: this(new TextMessageEncodingBindingElement()) { }
public GZipMessageEncodingBindingElement(MessageEncodingBindingElement messageEncoderBindingElement)
{
this.innerBindingElement = messageEncoderBindingElement;
}
public MessageEncodingBindingElement InnerMessageEncodingBindingElement
{
get { return innerBindingElement; }
set { innerBindingElement = value; }
}
//Main entry point into the encoder binding element.
// Called by WCF to get the factory that creates the
//message encoder.
public override MessageEncoderFactory CreateMessageEncoderFactory()
{
return new
GZipMessageEncoderFactory(innerBindingElement.CreateMessageEncoderFactory());
}
public override MessageVersion MessageVersion
{
get { return innerBindingElement.MessageVersion; }
set { innerBindingElement.MessageVersion = value; }
}
public override BindingElement Clone()
{
return new
GZipMessageEncodingBindingElement(this.innerBindingElement);
}
public override T GetProperty<T>(BindingContext context)
{
if (typeof(T) == typeof(XmlDictionaryReaderQuotas))
{
return innerBindingElement.GetProperty<T>(context);
}
else
{
return base.GetProperty<T>(context);
}
}
public override IChannelFactory<TChannel> BuildChannelFactory<TChannel>(BindingContext context)
{
if (context == null)
throw new ArgumentNullException("context");
context.BindingParameters.Add(this);
return context.BuildInnerChannelFactory<TChannel>();
}
public override IChannelListener<TChannel> BuildChannelListener<TChannel>(BindingContext context)
{
if (context == null)
throw new ArgumentNullException("context");
context.BindingParameters.Add(this);
return context.BuildInnerChannelListener<TChannel>();
}
public override bool CanBuildChannelListener<TChannel>(BindingContext context)
{
if (context == null)
throw new ArgumentNullException("context");
context.BindingParameters.Add(this);
return context.CanBuildInnerChannelListener<TChannel>();
}
void IPolicyExportExtension.ExportPolicy(MetadataExporter exporter, PolicyConversionContext policyContext)
{
if (policyContext == null)
{
throw new ArgumentNullException("policyContext");
}
XmlDocument document = new XmlDocument();
policyContext.GetBindingAssertions().Add(document.CreateElement(
GZipMessageEncodingPolicyConstants.GZipEncodingPrefix,
GZipMessageEncodingPolicyConstants.GZipEncodingName,
GZipMessageEncodingPolicyConstants.GZipEncodingNamespace));
}
}
Vegye figyelembe, hogy GZipMessageEncodingBindingElement az osztály implementálja az IPolicyExportExtension interfészt, így ez a kötési elem exportálható szabályzatként a metaadatokban, ahogyan az az alábbi példában is látható.
<wsp:Policy wsu:Id="BufferedHttpSampleServer_ISampleServer_policy">
<wsp:ExactlyOne>
<wsp:All>
<gzip:text xmlns:gzip=
"http://schemas.microsoft.com/ws/06/2004/mspolicy/netgzip1" />
<wsaw:UsingAddressing />
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
Az GZipMessageEncodingBindingElementImporter osztály implementálja a IPolicyImportExtension interfészt, és importálási szabályzatot alkalmaz a GZipMessageEncodingBindingElement-hez. Svcutil.exe eszközzel házirendeket importálhat a konfigurációs fájlba. A(z) GZipMessageEncodingBindingElement kezeléséhez a következőket kell hozzáadnia Svcutil.exe.config-hez.
<configuration>
<system.serviceModel>
<extensions>
<bindingElementExtensions>
<add name="gzipMessageEncoding"
type=
"Microsoft.ServiceModel.Samples.GZipMessageEncodingElement, GZipEncoder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</bindingElementExtensions>
</extensions>
<client>
<metadata>
<policyImporters>
<remove type=
"System.ServiceModel.Channels.MessageEncodingBindingElementImporter, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<extension type=
"Microsoft.ServiceModel.Samples.GZipMessageEncodingBindingElementImporter, GZipEncoder, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</policyImporters>
</metadata>
</client>
</system.serviceModel>
</configuration>
Most, hogy van egy megfelelő kötési elem a tömörítési kódoló számára, programozott módon beköthető a szolgáltatásba vagy az ügyfélbe egy új, egyéni kötési objektum létrehozásával és az egyéni kötési elem hozzáadásával, ahogy az az alábbi mintakódban látható.
ICollection<BindingElement> bindingElements = new List<BindingElement>();
HttpTransportBindingElement httpBindingElement = new HttpTransportBindingElement();
GZipMessageEncodingBindingElement compBindingElement = new GZipMessageEncodingBindingElement ();
bindingElements.Add(compBindingElement);
bindingElements.Add(httpBindingElement);
CustomBinding binding = new CustomBinding(bindingElements);
binding.Name = "SampleBinding";
binding.Namespace = "http://tempuri.org/bindings";
Bár ez elegendő lehet a felhasználói forgatókönyvek többségéhez, a fájlkonfiguráció támogatása kritikus fontosságú, ha egy szolgáltatást webre kell üzemeltetni. A webes forgatókönyv támogatásához egyéni konfigurációkezelőt kell kidolgoznia, hogy lehetővé tegye egy egyéni kötéselem konfigurálását egy fájlban.
A kötési elemhez konfigurációkezelőt hozhat létre a konfigurációs rendszer tetején. A kötéselem konfigurációkezelőjének az osztályból BindingElementExtensionElement kell származnia. A BindingElementExtensionElement.BindingElementType konfigurációs rendszer tájékoztatja a szakaszhoz létrehozandó kötési elem típusáról. A beállítható elemek minden aspektusát BindingElement tulajdonságokként kell elérhetővé tenni a BindingElementExtensionElement származtatott osztályban. A ConfigurationPropertyAttribute konfigurációelem-attribútumok tulajdonságokhoz való leképezésében és az alapértelmezett értékek beállításában segít, ha az attribútumok hiányoznak. A konfiguráció értékeinek betöltése és a tulajdonságokra való alkalmazása után a rendszer meghívja a BindingElementExtensionElement.CreateBindingElement metódust, amely a tulajdonságokat egy kötéselem konkrét példányává alakítja. A BindingElementExtensionElement.ApplyConfiguration metódust arra használják, hogy a BindingElementExtensionElement származtatott osztály tulajdonságait olyan értékekké konvertálják, amelyeket az újonnan létrehozott kötéselemen kell beállítani.
Az alábbi mintakód bemutatja a GZipMessageEncodingElement megvalósítását.
public class GZipMessageEncodingElement : BindingElementExtensionElement
{
public GZipMessageEncodingElement()
{
}
//Called by the WCF to discover the type of binding element this
//config section enables
public override Type BindingElementType
{
get { return typeof(GZipMessageEncodingBindingElement); }
}
//The only property we need to configure for our binding element is
//the type of inner encoder to use. Here, we support text and
//binary.
[ConfigurationProperty("innerMessageEncoding",
DefaultValue = "textMessageEncoding")]
public string InnerMessageEncoding
{
get { return (string)base["innerMessageEncoding"]; }
set { base["innerMessageEncoding"] = value; }
}
//Called by the WCF to apply the configuration settings (the
//property above) to the binding element
public override void ApplyConfiguration(BindingElement bindingElement)
{
GZipMessageEncodingBindingElement binding =
(GZipMessageEncodingBindingElement)bindingElement;
PropertyInformationCollection propertyInfo =
this.ElementInformation.Properties;
if (propertyInfo["innerMessageEncoding"].ValueOrigin !=
PropertyValueOrigin.Default)
{
switch (this.InnerMessageEncoding)
{
case "textMessageEncoding":
binding.InnerMessageEncodingBindingElement =
new TextMessageEncodingBindingElement();
break;
case "binaryMessageEncoding":
binding.InnerMessageEncodingBindingElement =
new BinaryMessageEncodingBindingElement();
break;
}
}
}
//Called by the WCF to create the binding element
protected override BindingElement CreateBindingElement()
{
GZipMessageEncodingBindingElement bindingElement =
new GZipMessageEncodingBindingElement();
this.ApplyConfiguration(bindingElement);
return bindingElement;
}
}
Ez a konfigurációkezelő a szolgáltatás vagy ügyfél App.config vagy Web.config a következő ábrázolásra képez le.
<gzipMessageEncoding innerMessageEncoding="textMessageEncoding" />
A konfigurációkezelő használatához regisztrálni kell a <system.serviceModel> elemen belül, ahogyan az az alábbi mintakonfigurációban látható.
<extensions>
<bindingElementExtensions>
<add
name="gzipMessageEncoding"
type=
"Microsoft.ServiceModel.Samples.GZipMessageEncodingElement,
GZipEncoder, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null" />
</bindingElementExtensions>
</extensions>
A kiszolgáló futtatásakor a műveleti kérelmek és a válaszok megjelennek a konzolablakban. Nyomja le az ENTER billentyűt az ablakban a kiszolgáló leállításához.
Press Enter key to Exit.
Server Echo(string input) called:
Client message: Simple hello
Server BigEcho(string[] input) called:
64 client messages
Az ügyfél futtatásakor a műveleti kérelmek és a válaszok megjelennek a konzolablakban. Nyomja le az ENTER billentyűt az ügyfélablakban az ügyfél leállításához.
Calling Echo(string):
Server responds: Simple hello Simple hello
Calling BigEcho(string[]):
Server responds: Hello 0
Press <ENTER> to terminate client.
A példa beállítása, elkészítése és futtatása
Telepítse a ASP.NET 4.0-t a következő paranccsal:
%windir%\Microsoft.NET\Framework\v4.0.XXXXX\aspnet_regiis.exe /i /enableGyőződjön meg arról, hogy elvégezte a Windows Communication Foundation-minták One-Time beállítási eljárását.
A megoldás létrehozásához kövesse a Windows Communication Foundation-minták készítésére vonatkozó utasításokat.
Ha a mintát egy vagy több gép közötti konfigurációban szeretné futtatni, kövesse A Windows Communication Foundation-minták futtatásacímű témakör utasításait.