Aracılığıyla paylaş


Veri Aktarımı Mimarisi Genel Bakış

Windows Communication Foundation (WCF) bir mesajlaşma altyapısı olarak düşünülebilir. daha fazla işlem için iletileri alabilir, işleyebilir ve kullanıcı koduna dağıtabilir veya kullanıcı kodu tarafından verilen verilerden iletiler oluşturup bir hedefe teslim edebilir. Gelişmiş geliştiricilere yönelik olan bu konu başlığında, iletileri ve kapsanan verileri işleme mimarisi açıklanmaktadır. Veri gönderme ve alma hakkında daha basit ve görev odaklı bir görünüm için bkz . Hizmet Sözleşmelerinde Veri AktarımıNı Belirtme.

Not

Bu konuda, WCF nesne modeli incelenerek görünür olmayan WCF uygulama ayrıntıları açıklanmaktadır. Belgelenmiş uygulama ayrıntılarıyla ilgili olarak iki dikkatli sözcük vardır. İlk olarak, açıklamalar basitleştirilmiştir; iyileştirmeler veya başka nedenlerle gerçek uygulama daha karmaşık olabilir. İkincisi, bunlar sürümden sürüme ve hatta bir hizmet sürümünde bildirimde bulunmadan değişebileceğinden, belgelenmiş olanlar bile olmak üzere belirli uygulama ayrıntılarına asla güvenmemelisiniz.

Temel Mimari

WCF ileti işleme özelliklerinin merkezinde, İleti Sınıfını Message Kullanma bölümünde ayrıntılı olarak açıklanan sınıfı yer alır. WCF'nin çalışma zamanı bileşenleri iki ana bölüme ayrılabilir: kanal yığını ve hizmet çerçevesi, Message sınıfı bağlantı noktasıdır.

Kanal yığını, geçerli Message bir örnek ile ileti verilerinin gönderilmesine veya alınmasına karşılık gelen bazı eylemler arasında dönüştürmeden sorumludur. Gönderen tarafta, kanal yığını geçerli Message bir örnek alır ve bir işlemden sonra, iletinin gönderilmesine mantıksal olarak karşılık gelen bir eylem gerçekleştirir. Eylem TCP veya HTTP paketleri gönderiyor, iletiyi Message Queuing'de kuyruğa almak, iletiyi veritabanına yazmak, dosya paylaşımına kaydetmek veya uygulamaya bağlı olarak başka bir eylem olabilir. En yaygın eylem, iletiyi bir ağ protokolü üzerinden göndermektir. Alma tarafında tam tersi gerçekleşir; bir eylem algılanır (gelen TCP veya HTTP paketleri veya başka bir eylem olabilir) ve işlendikten sonra kanal yığını bu eylemi geçerli Message bir örneğe dönüştürür.

WCF'yi doğrudan sınıfını Message ve kanal yığınını kullanarak kullanabilirsiniz. Ancak bunu yapmak zor ve zaman alır. Buna ek olarak, Message nesne meta veri desteği sağlamaz, bu nedenle WCF'yi bu şekilde kullanıyorsanız kesin olarak yazılan WCF istemcileri oluşturamazsınız.

Bu nedenle WCF, nesneleri oluşturmak ve almak Message için kullanabileceğiniz kullanımı kolay bir programlama modeli sağlayan bir hizmet çerçevesi içerir. Hizmet çerçevesi, hizmet sözleşmeleri ile hizmetleri .NET Framework türleriyle eşler ve yalnızca özniteliğiyle işaretlenmiş .NET Framework yöntemleri olan kullanıcı işlemlerine OperationContractAttribute iletiler iletir (daha fazla ayrıntı için bkz . Hizmet Sözleşmeleri Tasarlama). Bu yöntemlerin parametreleri ve dönüş değerleri olabilir. Hizmet tarafında, hizmet çerçevesi gelen Message örnekleri parametrelere dönüştürür ve dönüş değerlerini giden Message örneklere dönüştürür. İstemci tarafında ise tam tersini yapar. Örneğin, aşağıdaki işlemi göz önünde bulundurun FindAirfare .

[ServiceContract]
public interface IAirfareFinderService
{
    [OperationContract]
    int FindAirfare(string FromCity, string ToCity, out bool IsDirectFlight);
}
<ServiceContract()> _
Public Interface IAirfareFinderService

    <OperationContract()> _
    Function FindAirfare(ByVal FromCity As String, _
    ByVal ToCity As String, ByRef IsDirectFlight As Boolean) As Integer

End Interface

İstemcide çağrıldığını varsayalım FindAirfare . İstemcideki hizmet çerçevesi ve ToCity parametrelerini giden Message bir örneğe dönüştürür FromCity ve gönderilmek üzere kanal yığınına geçirir.

Hizmet tarafında, bir Message örnek kanal yığınından geldiğinde hizmet çerçevesi ve ToCity parametrelerini doldurmak FromCity için ilgili verileri iletiden ayıklar ve ardından hizmet tarafı FindAirfare yöntemini çağırır. Yöntemi döndürdüğünde, hizmet çerçevesi döndürülen tamsayı değerini ve IsDirectFlight çıkış parametresini alır ve bu bilgileri içeren bir Message nesne örneği oluşturur. Ardından örneği istemciye geri gönderilmek üzere kanal yığınına geçirir Message .

İstemci tarafında, yanıt iletisini içeren bir Message örnek kanal yığınından ortaya çıkar. Hizmet çerçevesi dönüş değerini ve IsDirectFlight değerini ayıklar ve bunları istemcinin çağırana döndürür.

Message Sınıfı

sınıfı Message , bir iletinin soyut bir gösterimi olarak tasarlanmıştır, ancak tasarımı SOAP iletisine güçlü bir şekilde bağlıdır. üç Message ana bilgi parçası içerir: ileti gövdesi, ileti üst bilgileri ve ileti özellikleri.

İleti Gövdesi

İleti gövdesi, iletinin gerçek veri yükünü temsil etmeye yöneliktir. İleti gövdesi her zaman xml bilgi kümesi olarak temsil edilir. Bu, WCF'de oluşturulan veya alınan tüm iletilerin XML biçiminde olması gerektiği anlamına gelmez. İleti gövdesini yorumlamaya karar vermek kanal yığınına bağlı. Bunu XML olarak yayabilir, başka bir biçime dönüştürebilir, hatta tamamen atlar. Elbette, WCF'nin sağladığı bağlamaların çoğuyla, ileti gövdesi bir SOAP zarfının gövde bölümünde XML içeriği olarak temsil edilir.

Sınıfın gövdesini Message temsil eden XML verilerine sahip bir arabellek içermemesi gerekir. Mantıksal olarak, Message bir XML Infoset içerir, ancak bu Infoset dinamik olarak oluşturulabilir ve bellekte hiçbir zaman fiziksel olarak bulunmayabilir.

İleti Gövdesine Veri Yerleştirme

İleti gövdesine veri koymak için tekdüzen bir mekanizma yoktur. sınıfının Message soyut bir yöntemi OnWriteBodyContents(XmlDictionaryWriter)vardır ve bunu alır XmlDictionaryWriter. Sınıfın Message her alt sınıfı bu yöntemi geçersiz kılmaktan ve kendi içeriğini yazmaktan sorumludur. İleti gövdesi mantıksal olarak oluşturan XML Bilgi Kümesi'ni OnWriteBodyContent içerir. Örneğin, aşağıdaki Message alt sınıfı göz önünde bulundurun.

public class AirfareRequestMessage : Message
{
    public string fromCity = "Tokyo";
    public string toCity = "London";
    //code omitted…
    protected override void OnWriteBodyContents(XmlDictionaryWriter w)
    {
        w.WriteStartElement("airfareRequest");
        w.WriteElementString("from", fromCity);
        w.WriteElementString("to", toCity);
        w.WriteEndElement();
    }

    public override MessageVersion Version
    {
        get { throw new NotImplementedException("The method is not implemented.") ; }
    }

    public override MessageProperties Properties
    {
        get { throw new Exception("The method or operation is not implemented."); }
    }
    public override MessageHeaders Headers
    {
        get { throw new Exception("The method or operation is not implemented."); }
    }

    public override bool IsEmpty
    {
        get
        {
            return base.IsEmpty;
        }
    }

    public override bool IsFault
    {
        get
        {
            return base.IsFault;
        }
    }
}
Public Class AirfareRequestMessage
    Inherits Message

    Public fromCity As String = "Tokyo"
    Public toCity As String = "London"
    ' Code omitted…
    Protected Overrides Sub OnWriteBodyContents(ByVal w As XmlDictionaryWriter)
        w.WriteStartElement("airfareRequest")
        w.WriteElementString("from", fromCity)
        w.WriteElementString("to", toCity)
        w.WriteEndElement()
    End Sub

    Public Overrides ReadOnly Property Version() As MessageVersion
        Get
            Throw New NotImplementedException("The method 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 Headers() As MessageHeaders
        Get
            Throw New Exception("The method or operation is not implemented.")
        End Get
    End Property


    Public Overrides ReadOnly Property IsEmpty() As Boolean
        Get
            Return MyBase.IsEmpty
        End Get
    End Property

    Public Overrides ReadOnly Property IsFault() As Boolean
        Get
            Return MyBase.IsFault
        End Get
    End Property
End Class

Fiziksel olarak, bir AirfareRequestMessage örnek yalnızca iki dize ("fromCity" ve "toCity") içerir. Ancak, mantıksal olarak ileti aşağıdaki XML bilgi kümesi içerir:

<airfareRequest>  
    <from>Tokyo</from>  
    <to>London</to>  
</airfareRequest>  

Elbette, işlem sözleşmesi parametrelerinden öncekine benzer bir ileti oluşturmak için hizmet çerçevesini kullanabileceğiniz için normalde bu şekilde ileti oluşturmazsınız. Ayrıca, sınıfın Message ortak içerik türlerine sahip iletiler oluşturmak için kullanabileceğiniz statik CreateMessage yöntemleri vardır: boş bir ileti, ile DataContractSerializerXML'ye seri hale getirilmiş bir nesne içeren bir ileti, SOAP hatası içeren bir ileti, ile temsil edilen XML içeren bir XmlReaderileti vb.

İleti Gövdesinden Veri Alma

İleti gövdesinde depolanan verileri iki ana yolla ayıklayabilirsiniz:

  • yöntemini çağırıp bir XML yazıcısı geçirerek ileti gövdesinin WriteBodyContents(XmlDictionaryWriter) tamamını bir kerede alabilirsiniz. İleti gövdesinin tamamı bu yazıcıya yazılır. İleti gövdesinin tamamını bir kerede almak, ileti yazma olarak da adlandırılır. Yazma öncelikli olarak ileti gönderirken kanal yığını tarafından yapılır; kanal yığınının bir bölümü genellikle ileti gövdesinin tamamına erişim elde eder, kodlar ve gönderir.

  • İleti gövdesinden bilgi edinmenin bir diğer yolu da xml okuyucuyu çağırmak GetReaderAtBodyContents() ve almaktır. Daha sonra okuyucuda yöntemler çağrılarak ileti gövdesine gerektiği gibi sıralı olarak erişilebilir. İleti gövdesini parça parça almak, ileti okuma olarak da adlandırılır. İletiyi okumak öncelikli olarak hizmet çerçevesi tarafından iletileri alırken kullanılır. Örneğin, hizmet çerçevesi kullanımda olduğunda DataContractSerializer , gövde üzerinde bir XML okuyucu alır ve seri durumdan çıkarma altyapısına geçirir; bu da ileti öğesini öğe öğe okumaya ve ilgili nesne grafını derlemeye başlar.

İleti gövdesi yalnızca bir kez alınabilir. Bu, yalnızca ileriye doğru akışlarla çalışmayı mümkün kılar. Örneğin, dosyasından FileStream okuyan ve sonuçları XML Infoset olarak döndüren bir geçersiz kılma yazabilirsinizOnWriteBodyContents(XmlDictionaryWriter). Hiçbir zaman dosyanın başına "geri sarmanız" gerekmez.

WriteBodyContents ve GetReaderAtBodyContents yöntemleri, ileti gövdesinin daha önce hiç alınıp alınmadığını denetler ve sırasıyla veya OnGetReaderAtBodyContentsçağrısında OnWriteBodyContents bulunur.

WCF'de İleti Kullanımı

İletilerin çoğu giden (kanal yığını tarafından gönderilecek hizmet çerçevesi tarafından oluşturulanlar) veya gelen (kanal yığınından gelen ve hizmet çerçevesi tarafından yorumlananlar) olarak sınıflandırılabilir. Ayrıca, kanal yığını arabelleğe alınan veya akış modunda çalışabilir. Hizmet çerçevesi akışlı veya akışsız programlama modelini de kullanıma sunabilir. Bu, aşağıdaki tabloda listelenen servis taleplerinin yanı sıra uygulamalarının basitleştirilmiş ayrıntılarına yol açar.

İleti türü İletideki gövde verileri Yazma (OnWriteBodyContents) uygulaması Read (OnGetReaderAtBodyContents) Uygulaması
Giden, akışsız programlama modelinden oluşturuldu İletiyi yazmak için gereken veriler (örneğin, bir nesne ve DataContractSerializer onu serileştirmek için gereken örnek)* Depolanan verileri temel alarak iletiyi yazmak için özel mantık (örneğin, kullanılan seri hale getiriciyse çağrısı WriteObjectDataContractSerializer )* çağrısı, OnWriteBodyContentssonuçları arabelleğe alma, arabellek üzerinden XML okuyucu döndürme
Giden, akışlı programlama modelinden oluşturuldu Stream Yazılacak verilerle* Mekanizmayı kullanarak IStreamProvider depolanan akıştan veri yazma* çağrısı, OnWriteBodyContentssonuçları arabelleğe alma, arabellek üzerinden XML okuyucu döndürme
Akış kanalı yığınından gelen Stream üzerinden gelen verileri temsil eden bir XmlReader nesne kullanarak depolanan XmlReader içeriği yazma WriteNode Depolanan değeri verir XmlReader
Akışsız kanal yığınından gelen Üzerinde bir bulunan gövde verilerini içeren bir XmlReader arabellek kullanarak depolanan XmlReader içeriği yazar WriteNode Depolanan lang'i verir

* Bu öğeler doğrudan alt sınıflarda Message değil, sınıfın BodyWriter alt sınıflarında uygulanır. hakkında BodyWriterdaha fazla bilgi için bkz . İleti Sınıfını Kullanma.

İleti Üst Bilgileri

bir ileti üst bilgi içerebilir. Üst bilgi mantıksal olarak bir ad, ad alanı ve diğer birkaç özellik ile ilişkilendirilmiş bir XML Bilgi Kümesinden oluşur. İleti üst bilgilerine üzerindeki Messageözelliği kullanılarak Headers erişilir. Her üst bilgi bir MessageHeader sınıfla temsil edilir. Normalde, SOAP iletileriyle çalışmak üzere yapılandırılmış bir kanal yığını kullanılırken ileti üst bilgileri SOAP ileti üst bilgilerine eşlenir.

Bilgileri bir ileti üst bilgisine yerleştirmek ve bu üst bilgiden bilgi ayıklamak, ileti gövdesini kullanmaya benzer. Akış desteklenmediğinden işlem biraz basitleştirilmiştir. Aynı üst bilginin içeriğine birden çok kez erişmek mümkündür ve üst bilgiler rastgele sırayla erişilebilir ve üst bilgiler her zaman arabelleğe alınmaya zorlanır. Üst bilgi üzerinden XML okuyucu almak için genel amaçlı bir mekanizma yoktur, ancak WCF'nin içinde bu tür bir MessageHeader özelliğe sahip okunabilir bir üst bilgiyi temsil eden bir alt sınıf vardır. Bu tür, MessageHeader özel uygulama üst bilgilerine sahip bir ileti geldiğinde kanal yığını tarafından oluşturulur. Bu, hizmet çerçevesinin bu üst bilgileri yorumlamak için gibi bir seri durumdan DataContractSerializerçıkarma altyapısı kullanmasını sağlar.

Daha fazla bilgi için bkz . İleti Sınıfını Kullanma.

İleti Özellikleri

İleti özellikleri içerebilir. Özellik, bir dize adıyla ilişkilendirilmiş herhangi bir .NET Framework nesnesidir. Özelliklere üzerindeki Messageözelliği aracılığıyla Properties erişilir.

İleti gövdesinden ve ileti üst bilgilerinden farklı olarak (normalde sırasıyla SOAP gövdesine ve SOAP üst bilgilerine eşlenir), ileti özellikleri normalde iletilerle birlikte gönderilmez veya alınmaz. İleti özellikleri öncelikli olarak, ileti hakkındaki verileri kanal yığınındaki çeşitli kanallar arasında ve kanal yığını ile hizmet modeli arasında geçirmek için bir iletişim mekanizması olarak bulunur.

Örneğin, WCF'nin bir parçası olarak eklenen HTTP aktarım kanalı, istemcilere yanıt gönderirken "404 (Bulunamadı)" ve "500 (İç Sunucu Hatası)" gibi çeşitli HTTP durum kodları oluşturabilir. Yanıt iletisi göndermeden önce, öğesinin Message türünde HttpResponseMessagePropertybir nesnesi içeren "httpResponse" adlı bir özellik içerip içermediğini Properties denetler. Böyle bir özellik bulunursa özelliğine StatusCode bakar ve bu durum kodunu kullanır. Bulunamazsa, varsayılan "200 (Tamam)" kodu kullanılır.

Daha fazla bilgi için bkz . İleti Sınıfını Kullanma.

Bir Bütün Olarak İleti

Şimdiye kadar iletinin çeşitli bölümlerine yalıtılmış olarak erişme yöntemlerini ele aldık. Ancak sınıfı, iletinin Message tamamıyla bir bütün olarak çalışmak için yöntemler de sağlar. Örneğin, WriteMessage yöntemi iletinin tamamını bir XML yazıcısına yazar.

Bunun mümkün olması için, tüm Message örnek ile XML Infoset arasında bir eşleme tanımlanmalıdır. Aslında böyle bir eşleme vardır: WCF, bu eşlemeyi tanımlamak için SOAP standardını kullanır. Bir Message örnek XML Infoset olarak yazıldığında, sonuçta elde edilen Infoset, iletiyi içeren geçerli SOAP zarfıdır. Bu nedenle, WriteMessage normalde aşağıdaki adımları gerçekleştirir:

  1. SOAP zarf öğesi açma etiketini yazın.

  2. SOAP üst bilgi öğesi açma etiketini yazın, tüm üst bilgileri yazın ve üst bilgi öğesini kapatın.

  3. SOAP gövde öğesi açma etiketini yazın.

  4. Gövdesini yazmak için çağırın WriteBodyContents veya eşdeğer bir yöntem.

  5. Gövde ve zarf öğelerini kapatın.

Önceki adımlar SOAP standardına yakından bağlıdır. Bu, SOAP'nin birden çok sürümünün mevcut olması nedeniyle karmaşıktır, örneğin, SOAP zarf öğesinin kullanımdaki SOAP sürümünü bilmeden doğru bir şekilde yazılmasının mümkün olmamasıdır. Ayrıca, bazı durumlarda, bu karmaşık SOAP'ye özgü eşlemenin tamamen kapatılması istenebilir.

Bu amaçlar için üzerinde Messagebir Version özellik sağlanır. İletiyi yazarken kullanılacak SOAP sürümüne ayarlanabilir veya SOAP'ye özgü eşlemeleri önlemek için None olarak ayarlanabilir. Version özelliği olarak Noneayarlanırsa, iletinin tamamıyla çalışan yöntemler, ileti yalnızca gövdesinden oluşuyormuş gibi davranır, örneğin, WriteMessage yukarıda listelenen birden çok adımı gerçekleştirmek yerine yalnızca çağrı WriteBodyContents yapar. Gelen iletilerde Version otomatik olarak algılanması ve doğru ayarlanması beklenir.

Kanal Yığını

Kanallar

Daha önce belirtildiği gibi, kanal yığını giden Message örnekleri bir eyleme (ağ üzerinden paket gönderme gibi) dönüştürmek veya bazı eylemleri (ağ paketlerini alma gibi) gelen Message örneklere dönüştürmekle sorumludur.

Kanal yığını, sırayla sıralanmış bir veya daha fazla kanaldan oluşur. Giden Message örnek yığındaki ilk kanala geçirilir (en üstteki kanal olarak da adlandırılır), bu da bunu yığında bir sonraki kanala geçirir ve bu şekilde devam eder. İleti, aktarım kanalı olarak adlandırılan son kanalda sonlanır. Gelen iletiler aktarım kanalından gelir ve kanaldan yığına kanala geçirilir. En üstteki kanaldan, ileti genellikle hizmet çerçevesine geçirilir. Bu, uygulama iletileri için her zamanki desen olsa da, bazı kanallar biraz farklı çalışabilir, örneğin, yukarıdaki bir kanaldan ileti gönderilmeden kendi altyapı iletilerini gönderebilirler.

Kanallar, yığından geçerken ileti üzerinde çeşitli şekillerde çalışabilir. En yaygın işlem, giden iletiye üst bilgi eklemek ve gelen iletide üst bilgileri okumaktır. Örneğin, bir kanal iletinin dijital imzasını hesaplayıp üst bilgi olarak ekleyebilir. Kanal, gelen iletilerde bu dijital imza üst bilgisini de inceleyip geçerli bir imzası olmayan iletilerin kanal yığınına çıkış yapmasını engelleyebilir. Kanallar genellikle ileti özelliklerini de ayarlar veya inceler. İleti gövdesi genellikle değiştirilmez, ancak buna izin verilir, örneğin WCF güvenlik kanalı ileti gövdesini şifreleyebilir.

Aktarım Kanalları ve İleti Kodlayıcıları

Yığındaki en alttaki kanal, diğer kanallar tarafından değiştirildiği gibi giden bir Messageöğesini gerçekten bir eyleme dönüştürmekle sorumludur. Alma tarafında bu, bazı eylemleri diğer kanalların işlediği bir Message eyleme dönüştüren kanaldır.

Daha önce belirtildiği gibi, eylemler değişebilir: çeşitli protokoller üzerinden ağ paketleri gönderme veya alma, iletiyi veritabanında okuma veya yazma ya da iletiye birkaç örnek vermek için Message Queuing kuyruğunda kuyruğa alma veya kuyruğa alma. Tüm bu eylemlerin tek bir ortak yanı vardır: WCFMessage örneği ile gönderilebilen, alınabilen, okunabilen, yazılabilir, kuyruğa alınabilen veya sıralanabilir gerçek bir bayt grubu arasında dönüştürme gerektirir. bir Message bayt grubuna dönüştürme işlemi kodlama olarak adlandırılır ve bir bayt grubundan oluşturma Message işleminin ters işlemi kod çözme olarak adlandırılır.

Çoğu aktarım kanalı, kodlama ve kod çözme işini gerçekleştirmek için ileti kodlayıcıları olarak adlandırılan bileşenleri kullanır. İleti kodlayıcı sınıfın MessageEncoder alt sınıfıdır. MessageEncoderve WriteMessage bayt grupları arasında Message dönüştürmek için çeşitli ReadMessage ve yöntem aşırı yüklemeleri içerir.

Gönderen tarafta arabelleğe alma aktarım kanalı, üzerindeki bir kanaldan aldığı nesneyi öğesine WriteMessagegeçirirMessage. Daha sonra eylemini gerçekleştirmek için kullandığı bir bayt dizisi alır (örneğin, bu baytları geçerli TCP paketleri olarak paketleme ve doğru hedefe gönderme). Akış aktarım kanalı önce bir Stream (örneğin, giden TCP bağlantısı üzerinden) oluşturur ve ardından hem hem Message de Stream 'yi uygun WriteMessage aşırı yüklemeye geçirerek iletiyi yazar.

Alma tarafında, arabelleğe alma aktarım kanalı gelen baytları (örneğin, gelen TCP paketlerinden) bir diziye ayıklar ve kanal yığınına daha fazla geçirebileceği bir Message nesne almak için çağırırReadMessage. Akış aktarım kanalı bir Stream nesne (örneğin, gelen TCP bağlantısı üzerinden ağ akışı) oluşturur ve nesneyi geri Message almak için bunu geçirirReadMessage.

Aktarım kanalları ile ileti kodlayıcı arasındaki ayrım zorunlu değildir; ileti kodlayıcı kullanmayan bir aktarım kanalı yazmak mümkündür. Ancak, bu ayrılmanın avantajı kompozisyon kolaylığıdır. Aktarım kanalı yalnızca tabanını MessageEncoderkullandığı sürece, herhangi bir WCF veya üçüncü taraf ileti kodlayıcı ile çalışabilir. Benzer şekilde, aynı kodlayıcı normalde herhangi bir aktarım kanalında kullanılabilir.

İleti Kodlayıcı İşlemi

Bir kodlayıcının tipik çalışmasını açıklamak için aşağıdaki dört örneği göz önünde bulundurmak yararlıdır.

İşlem Yorum
Kodlama, Arabelleğe Alınan Arabelleğe alınan modda kodlayıcı normalde değişken boyutlu bir arabellek oluşturur ve ardından bunun üzerinde bir XML yazıcı oluşturur. Ardından kodlanan iletiyi çağırır WriteMessage(XmlWriter) ve bu konudaki önceki bölümde Message açıklandığı gibi üst bilgileri ve ardından kullanarak WriteBodyContents(XmlDictionaryWriter)gövdeyi yazar. Daha sonra aktarım kanalının kullanması için arabellek içeriği (bayt dizisi olarak temsil edilir) döndürülür.
Kodlama, Akışlı Akış modunda, işlem yukarıdakine benzer, ancak daha basittir. Arabelleğe gerek yoktur. Normalde akış üzerinde bir XML yazıcı oluşturulur ve WriteMessage(XmlWriter) bu yazıcıya yazmak için öğesinde Message çağrılır.
Kod Çözme, Arabelleğe Alınmış Arabelleğe alınmış modda kod çözme işlemi yapılırken, normalde arabelleğe alınan verileri içeren özel Message bir alt sınıf oluşturulur. İletinin üst bilgileri okunur ve ileti gövdesinde konumlandırılmış bir XML okuyucu oluşturulur. Bu, ile GetReaderAtBodyContents()döndürülecek okuyucudur.
Kod Çözme, Akışa Alma Akış modunda kod çözme işlemi yapılırken normalde özel bir İleti alt sınıfı oluşturulur. Akış, tüm üst bilgileri okuyacak ve ileti gövdesine yerleştirecek kadar gelişmiştir. Daha sonra akış üzerinden bir XML okuyucu oluşturulur. Bu, ile GetReaderAtBodyContents()döndürülecek okuyucudur.

Kodlayıcılar diğer işlevleri de gerçekleştirebilir. Örneğin, kodlayıcılar XML okuyucularını ve yazıcılarını havuza alabilir. Her gerektiğinde yeni bir XML okuyucu veya yazıcı oluşturmak pahalıdır. Bu nedenle kodlayıcılar normalde bir okuyucu havuzu ve yapılandırılabilir boyutta yazar havuzu tutar. Daha önce açıklanan kodlayıcı işleminin açıklamalarında, "XML okuyucu/yazıcı oluşturma" tümceciği her kullanıldığında, normalde "havuzdan bir tane alın veya yoksa oluşturun" anlamına gelir. Kodlayıcı (ve Message kod çözme sırasında oluşturduğu alt sınıflar), artık gerekli olmadığında (örneğin, kapatıldığında Message ) okuyucuları ve yazıcıları havuzlara döndürmek için mantık içerir.

WCF üç ileti kodlayıcı sağlar, ancak ek özel türler oluşturmak mümkündür. Sağlanan türler Metin, İkili ve İleti İletim İyileştirme Mekanizması 'dır (MTOM). Bunlar, İleti Kodlayıcı Seçme bölümünde ayrıntılı olarak açıklanmıştır.

IStreamProvider Arabirimi

Akışlı gövde içeren bir giden iletiyi XML yazıcısına yazarken, Message uygulamasında aşağıdakine OnWriteBodyContents(XmlDictionaryWriter) benzer bir çağrı dizisi kullanılır:

  • Akışın önüne gerekli bilgileri yazın (örneğin, açılış XML etiketi).

  • Akışı yazın.

  • Akışı takip eden tüm bilgileri yazın (örneğin, kapanış XML etiketi).

Bu, metin xml kodlamasına benzer kodlamalarla iyi çalışır. Ancak, bazı kodlamalar XML Infoset bilgilerini (örneğin, XML öğelerini başlatma ve sonlandırma etiketleri) öğelerin içinde bulunan verilerle birlikte yerleştirmez. Örneğin, MTOM kodlamasında ileti birden çok bölüme ayrılır. Bir bölüm, gerçek öğe içeriği için diğer bölümlere başvurular içerebilen XML Infoset'i içerir. XML Bilgi Kümesi normalde akışı yapılan içeriklerle karşılaştırıldığında küçüktür, bu nedenle Infoset'i arabelleğe almak, yazmak ve ardından içeriği akışlı bir şekilde yazmak mantıklıdır. Bu, kapanış öğesi etiketi yazıldığı sırada akışın henüz yazılmaması gerektiği anlamına gelir.

Bu amaçla arabirim IStreamProvider kullanılır. Arabirimi, yazılacak akışı döndüren bir GetStream() yönteme sahiptir. akışı yapılan ileti gövdesini OnWriteBodyContents(XmlDictionaryWriter) yazmanın doğru yolu aşağıdaki gibidir:

  1. Akışın önüne gerekli bilgileri yazın (örneğin, açılış XML etiketi).

  2. WriteValue Akışın yazılması için döndüren bir IStreamProviderIStreamProvider uygulama ile bir alan üzerindeki XmlDictionaryWriter aşırı yüklemeyi çağırın.

  3. Akışı takip eden tüm bilgileri yazın (örneğin, kapanış XML etiketi).

Bu yaklaşımla, XML yazıcısı akış verilerinin ne zaman çağrılıp GetStream() yazılabileceğine ilişkin bir seçime sahiptir. Örneğin, metinsel ve ikili XML yazıcıları bunu hemen çağırır ve akış içeriklerini başlangıç ve bitiş etiketleri arasında yazar. MTOM yazıcı, iletinin uygun bölümünü yazmaya hazır olduğunda daha sonra aramaya GetStream() karar verebilir.

Service Framework'te Verileri Temsil Etme

Bu konunun "Temel Mimari" bölümünde belirtildiği gibi, hizmet çerçevesi WCF'nin diğer şeylerin yanı sıra ileti verileri ve gerçek Message örnekler için kullanıcı dostu bir programlama modeli arasında dönüştürmeden sorumlu olan bölümüdür. Normalde, bir ileti değişimi hizmet çerçevesinde özniteliğiyle OperationContractAttribute işaretlenmiş bir .NET Framework yöntemi olarak temsil edilir. yöntemi bazı parametreleri alabilir ve bir dönüş değeri döndürebilir veya parametreleri (veya her ikisini birden) döndürebilir. Hizmet tarafında giriş parametreleri gelen iletiyi, dönüş değeri ve çıkış parametreleri giden iletiyi temsil eder. İstemci tarafında tersi doğrudur. Parametreleri ve dönüş değerini kullanarak iletileri açıklamaya yönelik programlama modeli, Hizmet Sözleşmelerinde Veri Aktarımını Belirtme bölümünde ayrıntılı olarak açıklanmıştır. Ancak, bu bölüm kısa bir genel bakış sağlayacaktır.

Programlama Modelleri

WCF hizmet çerçevesi, iletileri tanımlamak için beş farklı programlama modelini destekler:

1. Boş İleti

Bu en basit dava. Boş bir gelen iletiyi açıklamak için herhangi bir giriş parametresi kullanmayın.

[OperationContract]
int GetCurrentTemperature();
<OperationContract()> Function GetCurrentTemperature() As Integer

Boş bir giden iletiyi açıklamak için void dönüş değeri kullanın ve out parametresi kullanmayın:

[OperationContract]
void SetDesiredTemperature(int t);
<OperationContract()> Sub SetDesiredTemperature(ByVal t As Integer)

Bunun tek yönlü işlem sözleşmesinden farklı olduğunu unutmayın:

[OperationContract(IsOneWay = true)]
void SetLightbulb(bool isOn);
<OperationContract(IsOneWay:=True)> Sub SetLightbulb(ByVal isOn As Boolean)

SetDesiredTemperature Örnekte, iki yönlü ileti değişimi deseni açıklanmıştır. İşlemden bir ileti döndürülür, ancak boş olur. İşlemden hata döndürülmesi mümkündür. "Ampul Ayarla" örneğinde, ileti değişimi deseni tek yönlüdür, bu nedenle açıklanacağı bir giden ileti yoktur. Bu durumda hizmet istemciye herhangi bir durum bildiremez.

2. İleti Sınıfını Doğrudan Kullanma

Sınıfını Message (veya alt sınıflarından birini) doğrudan bir işlem sözleşmesinde kullanmak mümkündür. Bu durumda, hizmet çerçevesi Message işlemden kanal yığınına (veya tam tersi) iletir ve daha fazla işlem yapılmaz.

Doğrudan kullanmak Message için iki ana kullanım örneği vardır. Diğer programlama modellerinden hiçbiri iletinizi açıklamak için yeterli esneklik sunmadığında, bunu gelişmiş senaryolar için kullanabilirsiniz. Örneğin, bir iletiyi açıklamak için disk üzerindeki dosyaları kullanmak isteyebilirsiniz; dosyanın özellikleri ileti üst bilgilerine, dosyanın içeriği de ileti gövdesine dönüşebilir. Daha sonra aşağıdakine benzer bir şey oluşturabilirsiniz.

public class FileMessage : Message
// Code not shown.
Public Class FileMessage
    Inherits Message
    ' Code not shown.

bir işlem sözleşmesinde için ikinci yaygın kullanım Message , bir hizmetin belirli ileti içeriğini umursamaması ve ileti üzerinde kara kutu gibi davranmasıdır. Örneğin, iletileri birden çok alıcıya ileden bir hizmetiniz olabilir. Sözleşme aşağıdaki gibi yazılabilir.

[OperationContract]
public FileMessage GetFile()
{
    //code omitted…
    FileMessage fm = new FileMessage("myFile.xml");
    return fm;
}
<OperationContract()> Public Function GetFile() As FileMessage
    'code omitted…
    Dim fm As New FileMessage("myFile.xml")
    Return fm
End Function

Action="*" satırı, ileti göndermeyi etkili bir şekilde kapatır ve sözleşmeye gönderilen tüm iletilerin IForwardingService işleme doğru yol açmasını ForwardMessage sağlar. (Normalde dağıtıcı, hangi işleme yönelik olduğunu belirlemek için iletinin "Eylem" üst bilgisini inceler. Action="*", "Eylem üst bilgisinin tüm olası değerleri" anlamına gelir.) Tüm olası iletileri alabildiği için Action="*" ve Message'ın parametre olarak kullanılması "evrensel sözleşme" olarak bilinir. Tüm olası iletileri gönderebilmek için dönüş değeri olarak İleti'yi kullanın ve "*" olarak ayarlayın ReplyAction . Bu, hizmet çerçevesinin kendi Eylem üst bilgisini eklemesini engelleyerek, döndürülen nesneyi kullanarak Message bu üst bilgiyi denetlemenizi sağlar.

3. İleti Sözleşmeleri

WCF, iletileri açıklamak için ileti sözleşmeleri olarak adlandırılan bildirim temelli bir programlama modeli sağlar. Bu model, İleti Sözleşmelerini Kullanma bölümünde ayrıntılı olarak açıklanmıştır. Temelde, iletinin tamamı, ileti sözleşmesi sınıfının hangi bölümlerinin iletinin MessageBodyMemberAttribute hangi bölümüyle eşlenmesi gerektiğini açıklamak için ve MessageHeaderAttribute gibi öznitelikleri kullanan tek bir .NET Framework türüyle temsil edilir.

İleti sözleşmeleri, sonuçta elde edilen Message örnekler üzerinde çok fazla denetim sağlar (açıkçası sınıfı doğrudan kullanmak Message kadar fazla denetim olmasa da). Örneğin, ileti gövdeleri genellikle her biri kendi XML öğesiyle temsil edilen birden çok bilgi parçasından oluşur. Bu öğeler doğrudan gövdede (çıplak modda) oluşabilir veya kapsayan bir XML öğesinde sarmalanabilir. İleti sözleşmesi programlama modelini kullanmak, çıplak ve sarmalanmış kararı vermenizi ve sarmalayıcı adı ile ad alanının adını denetlemenizi sağlar.

İleti sözleşmesinin aşağıdaki kod örneği bu özellikleri gösterir.

[MessageContract(IsWrapped = true, WrapperName = "Order")]
public class SubmitOrderMessage
{
    [MessageHeader]
    public string customerID;
    [MessageBodyMember]
    public string item;
    [MessageBodyMember]
    public int quantity;
}
<MessageContract(IsWrapped:=True, WrapperName:="Order")> _
Public Class SubmitOrderMessage
    <MessageHeader()> Public customerID As String
    <MessageBodyMember()> Public item As String
    <MessageBodyMember()> Public quantity As Integer
End Class

Seri hale getirilecek şekilde işaretlenmiş öğeler ( MessageBodyMemberAttribute, MessageHeaderAttributeveya diğer ilgili özniteliklerle) ileti sözleşmesine katılmak için seri hale getirilebilir olmalıdır. Daha fazla bilgi için bu konunun devamında yer alan "Serileştirme" bölümüne bakın.

4. Parametreler

Çoğu zaman, birden çok veri parçası üzerinde işlem yapan bir işlemi açıklamak isteyen bir geliştiricinin, ileti sözleşmelerinin sağladığı denetim derecesine ihtiyacı yoktur. Örneğin, yeni hizmetler oluştururken, genellikle çıplak veya sarmalanmış kararı vermek ve sarmalayıcı öğe adına karar vermek istemezsiniz. Bu kararların alınması genellikle Web hizmetleri ve SOAP hakkında derin bilgi gerektirir.

WCF hizmet çerçevesi, bu seçenekleri kullanıcıya zorlamadan, ilgili birden çok bilgi parçası göndermek veya almak için en iyi ve en çok birlikte çalışabilen SOAP gösterimini otomatik olarak seçebilir. Bu, yalnızca bu bilgi parçalarını bir işlem sözleşmesinin parametreleri veya dönüş değerleri olarak tanımlayarak gerçekleştirilir. Örneğin, aşağıdaki işlem sözleşmesini göz önünde bulundurun.

[OperationContract]
void SubmitOrder(string customerID, string item, int quantity);
<OperationContract()> _
Sub SubmitOrder( _
    ByVal customerID As String, _
    ByVal item As String, _
    ByVal quantity As Integer)

Hizmet çerçevesi otomatik olarak üç bilgi parçasını da (customerID, itemve quantity) ileti gövdesine yerleştirmeye ve bunları adlı SubmitOrderRequestsarmalayıcı öğesine sarmalamaya karar verir.

Daha karmaşık ileti sözleşmesine veya tabanlı programlama modellerine geçmek için özel nedenler olmadığı sürece, gönderilecek veya Messagealınacak bilgilerin basit bir işlem sözleşmesi parametreleri listesi olarak açıklanması önerilen yaklaşımdır.

5. Akış

Bir işlem sözleşmesinde veya bir ileti sözleşmesinde alt sınıflarından birini veya tek ileti gövdesi parçası olarak kullanmak Stream , yukarıda açıklananlardan ayrı bir programlama modeli olarak kabul edilebilir. Stream Bu şekilde kullanmak, kendi akış uyumlu Message alt sınıfınızı yazmaktan kısa bir süre sonra sözleşmenizin akışlı bir şekilde kullanılabilir olacağını garanti etmenin tek yoludur. Daha fazla bilgi için bkz . Büyük Veri ve Akış.

Alt Stream sınıflarından biri veya alt sınıflarından biri bu şekilde kullanıldığında seri hale getirici çağrılmıyor. Giden iletiler için özel bir akış Message alt sınıfı oluşturulur ve akış, arabirimdeki bölümde IStreamProvider açıklandığı gibi yazılır. Hizmet çerçevesi, gelen iletiler için gelen ileti üzerinde bir Stream alt sınıf oluşturur ve bunu işleme sağlar.

Programlama Modeli Kısıtlamaları

Yukarıda açıklanan programlama modelleri rastgele birleştirilemez. Örneğin, bir işlem bir ileti sözleşmesi türünü kabul ederse, ileti sözleşmesinin tek giriş parametresi olması gerekir. Ayrıca işlemin boş bir ileti (dönüş türü void) veya başka bir ileti sözleşmesi döndürmesi gerekir. Bu programlama modeli kısıtlamaları, belirli programlama modellerinin konu başlıklarında açıklanmıştır: İleti Sözleşmelerini Kullanma, İleti Sınıfını Kullanma ve Büyük Veri ve Akış.

İleti Biçimlendiricileri

Yukarıda açıklanan programlama modelleri, hizmet çerçevesine ileti biçimlendiricileri olarak adlandırılan bileşenleri takarak desteklenir. İleti biçimlendiricileri, sırasıyla istemcilerde ve hizmet WCF istemcilerinde kullanılmak üzere veya IDispatchMessageFormatter arabirimini ya da ikisini birden uygulayan IClientMessageFormatter türlerdir.

İleti biçimlendiricileri normalde davranışlara göre takılıdır. Örneğin, DataContractSerializerOperationBehavior veri sözleşmesi ileti biçimlendiricisini ekler. Bu işlem, hizmet tarafında yönteminde doğru biçimlendiriciye ayarlanarak Formatter veya istemci tarafında yönteminde ApplyClientBehavior(OperationDescription, ClientOperation) doğru biçimlendiriciye ayarlanarak FormatterApplyDispatchBehavior(OperationDescription, DispatchOperation) gerçekleştirilir.

Aşağıdaki tablolarda, bir ileti biçimlendiricinin uygulayabileceği yöntemler listelenir.

Arabirim Metot Eylem
IDispatchMessageFormatter DeserializeRequest(Message, Object[]) Gelen Message bir işlemi işlem parametrelerine dönüştürür
IDispatchMessageFormatter SerializeReply(MessageVersion, Object[], Object) İşlemden giden Message dönüş değeri/çıkış parametreleri oluşturur
IClientMessageFormatter SerializeRequest(MessageVersion, Object[]) İşlem parametrelerinden giden Message oluşturur
IClientMessageFormatter DeserializeReply(Message, Object[]) Gelen Message bir değeri dönüş değerine/çıkış parametrelerine dönüştürür

Serileştirme

İleti içeriğini açıklamak için ileti sözleşmelerini veya parametrelerini her kullandığınızda, .NET Framework türleri ile XML Infoset gösterimi arasında dönüştürme yapmak için serileştirme kullanmanız gerekir. Serileştirme, WCF'deki diğer yerlerde kullanılır; örneğin, Message bir nesnede seri durumdan çıkarılmış iletinin tüm gövdesini okumak için kullanabileceğiniz genel GetBody bir yöntemi vardır.

WCF, parametreleri ve ileti bölümlerini seri hale getirme ve seri durumdan çıkarma için "kullanıma hazır" iki serileştirme teknolojisini destekler: ve DataContractSerializerXmlSerializer. Ayrıca, özel serileştiriciler yazabilirsiniz. Ancak, WCF'nin diğer bölümleri (Genel GetBody yöntem veya SOAP hata serileştirmesi gibi) yalnızca XmlObjectSerializer alt sınıfları (DataContractSerializer ve NetDataContractSerializer, XmlSerializerdeğil) kullanacak şekilde kısıtlanabilir, hatta yalnızca DataContractSerializerkullanmak için sabit kodlanmış olabilir.

XmlSerializer, ASP.NET Web hizmetlerinde kullanılan serileştirme altyapısıdır. DataContractSerializer, yeni veri sözleşmesi programlama modelini anlayan yeni serileştirme altyapısıdır. DataContractSerializer varsayılan seçenektir ve öğesini kullanma XmlSerializer seçeneği özniteliği kullanılarak DataContractFormatAttribute işlem başına temelinde yapılabilir.

DataContractSerializerOperationBehaviorve XmlSerializerOperationBehavior sırasıyla ve XmlSerializeriçin DataContractSerializer ileti biçimlendiricilerini takmaktan sorumlu işlem davranışlarıdır. DavranışDataContractSerializerOperationBehavior, (Tek Başına SeriLeştirmeYi Kullanma bölümünde ayrıntılı olarak açıklanmıştır) dahil olmak üzere NetDataContractSerializer , 'den XmlObjectSerializertüretilen herhangi bir seri hale getiriciyle çalışabilir. Davranış, seri hale getiriciyi CreateSerializer almak için sanal yöntem aşırı yüklemelerinden birini çağırır. Farklı bir seri hale getirici eklemek için yeni DataContractSerializerOperationBehavior bir alt sınıf oluşturun ve her iki aşırı yüklemeyi de CreateSerializer geçersiz kılın.

Ayrıca bkz.