Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Sampel Seumur Hidup menunjukkan cara menulis ekstensi Windows Communication Foundation (WCF) untuk menyediakan layanan seumur hidup kustom untuk instans layanan WCF bersama.
Nota
Prosedur penyiapan dan instruksi build untuk sampel ini terletak di akhir artikel ini.
Penginstansian Bersama
WCF menawarkan beberapa mode instansiasi untuk instans layanan Anda. Mode instancing bersama yang tercakup dalam artikel ini menyediakan cara untuk berbagi instans layanan antara beberapa saluran. Klien dapat menghubungi metode pabrik dalam layanan dan membuat saluran baru untuk memulai komunikasi. Cuplikan kode berikut menunjukkan bagaimana aplikasi klien membuat saluran baru ke instans layanan yang ada:
// Create a header for the shared instance id
MessageHeader shareableInstanceContextHeader = MessageHeader.CreateHeader(
CustomHeader.HeaderName,
CustomHeader.HeaderNamespace,
Guid.NewGuid().ToString());
// Create the channel factory
ChannelFactory<IEchoService> channelFactory =
new ChannelFactory<IEchoService>("echoservice");
// Create the first channel
IEchoService proxy = channelFactory.CreateChannel();
// Call an operation to create shared service instance
using (new OperationContextScope((IClientChannel)proxy))
{
OperationContext.Current.OutgoingMessageHeaders.Add(shareableInstanceContextHeader);
Console.WriteLine("Service returned: " + proxy.Echo("Apple"));
}
((IChannel)proxy).Close();
// Create the second channel
IEchoService proxy2 = channelFactory.CreateChannel();
// Call an operation using the same header that will reuse the shared service instance
using (new OperationContextScope((IClientChannel)proxy2))
{
OperationContext.Current.OutgoingMessageHeaders.Add(shareableInstanceContextHeader);
Console.WriteLine("Service returned: " + proxy2.Echo("Apple"));
}
Tidak seperti mode instancing lainnya, mode instancing bersama menyediakan cara yang unik untuk melepaskan instans layanan. Secara default, ketika semua saluran ditutup untuk InstanceContext, runtime layanan WCF memeriksa untuk melihat apakah layanan InstanceContextMode dikonfigurasi ke PerCall atau PerSession, dan jika demikian merilis instans dan mengklaim sumber daya. Jika kustom IInstanceContextProvider sedang digunakan, WCF memanggil metode IsIdle implementasi penyedia sebelum melepaskan instans. Jika IsIdle mengembalikan instans true dirilis, jika tidak IInstanceContextProvider , implementasi bertanggung jawab untuk memberi tahu Dispatcher status menganggur dengan menggunakan metode panggilan balik. Ini dilakukan dengan memanggil metode NotifyIdle penyedia.
Sampel ini menunjukkan bagaimana Anda dapat menunda merilis InstanceContext dengan batas waktu menganggur 20 detik.
Memperluas InstanceContext
Di WCF, InstanceContext adalah tautan antara instans layanan dan Dispatcher. WCF memungkinkan Anda untuk memperluas komponen runtime ini dengan menambahkan status atau perilaku baru dengan menggunakan pola objek yang dapat diperluas. Pola objek yang dapat diperluas digunakan dalam WCF untuk memperluas kelas runtime yang ada dengan fungsionalitas baru atau untuk menambahkan fitur status baru ke objek. Ada tiga antarmuka dalam pola objek yang dapat diperluas: IExtensibleObject<T>, , IExtension<T>dan IExtensionCollection<T>.
Antarmuka IExtensibleObject<T> diimplementasikan oleh objek untuk memungkinkan ekstensi yang menyesuaikan fungsionalitasnya.
Antarmuka IExtension<T> diimplementasikan oleh objek yang dapat menjadi ekstensi kelas jenis T.
Dan akhirnya, antarmuka IExtensionCollection<T> adalah kumpulan dari implementasi IExtension<T> yang memungkinkan pengambilan implementasi dari tipe IExtension<T>.
Oleh karena itu, untuk memperluas InstanceContext, Anda harus menerapkan IExtension<T> antarmuka. Dalam proyek sampel ini, CustomLeaseExtension kelas berisi implementasi ini.
class CustomLeaseExtension : IExtension<InstanceContext>
{
}
Antarmuka IExtension<T> memiliki dua metode Attach dan Detach. Seperti namanya, kedua metode ini dipanggil ketika runtime menyambungkan dan memutuskan ekstensi pada instans kelas InstanceContext. Dalam sampel ini, metode Attach digunakan untuk memantau objek InstanceContext yang dimiliki oleh instans ekstensi saat ini.
InstanceContext owner;
public void Attach(InstanceContext owner)
{
this.owner = owner;
}
Selain itu, Anda harus menambahkan implementasi yang diperlukan ke ekstensi untuk memberikan dukungan seumur hidup yang diperpanjang. Oleh karena itu, ICustomLease antarmuka dideklarasikan dengan metode yang diinginkan dan diimplementasikan di CustomLeaseExtension kelas .
interface ICustomLease
{
bool IsIdle { get; }
InstanceContextIdleCallback Callback { get; set; }
}
class CustomLeaseExtension : IExtension<InstanceContext>, ICustomLease
{
}
Ketika WCF memanggil metode IsIdle yang merupakan bagian dari implementasi IInstanceContextProvider, panggilan ini dirutekan ke metode IsIdle dari CustomLeaseExtension. Kemudian, CustomLeaseExtension memeriksa status privatnya untuk melihat apakah InstanceContext tidak aktif. Jika diam, ia akan mengembalikan true. Jika tidak, ini memulai timer untuk jumlah masa pakai yang diperpanjang yang ditentukan.
public bool IsIdle
{
get
{
lock (thisLock)
{
if (isIdle)
{
return true;
}
else
{
StartTimer();
return false;
}
}
}
}
Dalam peristiwa timer Elapsed , fungsi panggilan balik di Dispatcher dipanggil untuk memulai siklus pembersihan lain.
void idleTimer_Elapsed(object sender, ElapsedEventArgs args)
{
lock (thisLock)
{
StopTimer();
isIdle = true;
Utility.WriteMessageToConsole(
ResourceHelper.GetString("MsgLeaseExpired"));
callback(owner);
}
}
Tidak ada cara untuk memperbarui timer yang sedang berjalan ketika pesan baru tiba untuk instans yang dipindahkan ke status menganggur.
Sampel mengimplementasikan IInstanceContextProvider untuk mencegat panggilan ke IsIdle metode dan merutekannya ke CustomLeaseExtension. Implementasi IInstanceContextProvider terkandung dalam CustomLifetimeLease kelas. Metode IsIdle ini dipanggil ketika WCF akan merilis instans layanan. Namun, hanya ada satu implementasi tertentu ISharedSessionInstance dalam koleksi dari ServiceBehavior IInstanceContextProvider. Ini berarti tidak ada cara untuk mengetahui apakah InstanceContext ditutup pada saat WCF memeriksa metode IsIdle. Oleh karena itu, sampel ini menggunakan penguncian utas untuk membuat serialisasi permintaan ke metode IsIdle.
Penting
Menggunakan penguncian utas bukanlah pendekatan yang direkomendasikan karena serialisasi dapat sangat memengaruhi performa aplikasi Anda.
Bidang anggota privat digunakan di kelas CustomLifetimeLease untuk melacak status menganggur dan dikembalikan oleh metode IsIdle. Setiap kali metode dipanggil IsIdle , isIdle bidang dikembalikan dan diatur ulang ke false. Sangat penting untuk mengatur nilai ini ke false untuk memastikan Dispatcher memanggil NotifyIdle metode .
public bool IsIdle(InstanceContext instanceContext)
{
get
{
lock (thisLock)
{
//...
bool idleCopy = isIdle;
isIdle = false;
return idleCopy;
}
}
}
Jika metode IInstanceContextProvider.IsIdle mengembalikan false, Dispatcher mendaftarkan fungsi panggilan balik dengan menggunakan metode NotifyIdle. Metode ini menerima referensi ke InstanceContext yang sedang dirilis. Oleh karena itu, kode sampel dapat melakukan kueri jenis ekstensi ICustomLease dan memeriksa properti ICustomLease.IsIdle dalam keadaan yang diperluas.
public void NotifyIdle(InstanceContextIdleCallback callback,
InstanceContext instanceContext)
{
lock (thisLock)
{
ICustomLease customLease =
instanceContext.Extensions.Find<ICustomLease>();
customLease.Callback = callback;
isIdle = customLease.IsIdle;
if (isIdle)
{
callback(instanceContext);
}
}
}
ICustomLease.IsIdle Sebelum properti dicentang, properti Callback perlu diatur karena ini penting untuk CustomLeaseExtension memberi tahu Dispatcher ketika diam. Jika ICustomLease.IsIdle mengembalikan true, anggota privat isIdle hanya disetel dalam CustomLifetimeLease ke true dan memanggil fungsi callback. Karena kode menyimpan kunci, utas lain tidak dapat mengubah nilai anggota privat ini. Dan lain kali Dispatcher memanggil IInstanceContextProvider.IsIdle, itu mengembalikan true dan memungkinkan Dispatcher merilis instans tersebut.
Sekarang setelah dasar untuk ekstensi kustom selesai, ekstensi kustom tersebut harus diintegrasikan ke dalam model layanan. Untuk menghubungkan implementasi CustomLeaseExtension ke InstanceContext, WCF menyediakan antarmuka IInstanceContextInitializer untuk melakukan bootstrap InstanceContext. Dalam contoh, kelas CustomLeaseInitializer menangani antarmuka ini dan menambahkan contoh CustomLeaseExtension ke koleksi Extensions pada satu-satunya inisialisasi metode. Metode ini dipanggil oleh Dispatcher saat menginisialisasi InstanceContext.
public void InitializeInstanceContext(InstanceContext instanceContext,
System.ServiceModel.Channels.Message message, IContextChannel channel)
//...
IExtension<InstanceContext> customLeaseExtension =
new CustomLeaseExtension(timeout, headerId);
instanceContext.Extensions.Add(customLeaseExtension);
}
Implementasi IInstanceContextProvider akhirnya terhubung ke model layanan menggunakan implementasi IServiceBehavior. Implementasi ini ditempatkan di CustomLeaseTimeAttribute kelas dan juga berasal dari Attribute kelas dasar untuk mengekspos perilaku ini sebagai atribut.
public void ApplyDispatchBehavior(ServiceDescription description,
ServiceHostBase serviceHostBase)
{
CustomLifetimeLease customLease = new CustomLifetimeLease(timeout);
foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher cd = cdb as ChannelDispatcher;
if (cd != null)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
ed.DispatchRuntime.InstanceContextProvider = customLease;
}
}
}
}
Perilaku ini dapat ditambahkan ke kelas layanan sampel dengan menganotasinya dengan CustomLeaseTime atribut .
[CustomLeaseTime(Timeout = 20000)]
public class EchoService : IEchoService
{
//…
}
Saat Anda menjalankan sampel, permintaan dan respons operasi ditampilkan di jendela layanan dan konsol klien. Tekan ENTER di setiap jendela konsol untuk mematikan layanan dan klien.
Untuk menyiapkan, mengompilasi, dan menjalankan sampel
Pastikan Anda telah melakukan Prosedur PenyiapanOne-Time untuk Sampel Windows Communication Foundation.
Untuk membangun solusi edisi C# atau Visual Basic .NET, ikuti instruksi di Membangun Sampel Windows Communication Foundation.
Untuk menjalankan sampel dalam konfigurasi satu atau lintas komputer, ikuti instruksi di Menjalankan Sampel Windows Communication Foundation.