Bagikan melalui


Objek yang Dapat Diperluas

Pola objek yang dapat diperluas digunakan untuk memperluas kelas runtime yang ada dengan fungsionalitas baru atau untuk menambahkan status baru ke objek. Ekstensi, yang melekat pada salah satu objek yang dapat diperluas, memungkinkan perilaku pada tahap yang sangat berbeda dalam pemrosesan untuk mengakses status bersama dan fungsionalitas yang melekat pada objek umum yang dapat diakses.

Pola <T> IExtensibleObject

Ada tiga antarmuka dalam pola objek yang dapat diperluas: IExtensibleObject<T>, IExtension<T>, dan IExtensionCollection<T>.

Antarmuka IExtensibleObject<T> diimplementasikan oleh jenis yang memungkinkan objek IExtension<T> untuk menyesuaikan fungsionalitasnya.

Objek yang dapat diperluas memungkinkan agregasi dinamis objek IExtension<T>. Objek IExtension<T> ditandai dengan antarmuka berikut:

public interface IExtension<T>
where T : IExtensibleObject<T>
{
    void Attach(T owner);
    void Detach(T owner);
}

Pembatasan jenis menjamin bahwa ekstensi hanya dapat ditentukan untuk kelas yang IExtensibleObject<T>. Attach dan Detach memberikan pemberitahuan agregasi atau disagregasi.

Hal ini berlaku untuk implementasi untuk membatasi kapan mereka dapat ditambahkan dan dihapus dari pemilik. Misalnya, Anda dapat melarang penghapusan sepenuhnya, melarang penambahan atau penghapusan ekstensi saat pemilik atau ekstensi berada dalam status tertentu, melarang penambahan ke beberapa pemilik secara bersamaan, atau hanya mengizinkan satu penambahan diikuti dengan satu penghapusan.

IExtension<T> tidak menyiratkan setiap interaksi dengan antarmuka terkelola standar lainnya. Secara khusus, metode IDisposable.Dispose pada objek pemilik biasanya tidak melepaskan ekstensinya.

Ketika ekstensi ditambahkan ke koleksi, Attach dipanggil sebelum masuk ke koleksi. Ketika ekstensi dihapus dari koleksi, Detach dipanggil setelah dihapus. Hal ini berarti (dengan asumsi sinkronisasi yang sesuai) ekstensi hanya dapat mengandalkan ditemukan dalam koleksi saat berada di antara Attach dan Detach.

Objek yang diteruskan ke FindAll atau Find tidak harus IExtension<T> (misalnya, Anda dapat meneruskan objek apa pun), tetapi ekstensi yang dikembalikan adalah IExtension<T>.

Jika tidak ada ekstensi dalam koleksi yang merupakan IExtension<T>, Find mengembalikan nol, dan FindAll mengembalikan koleksi kosong. Jika beberapa ekstensi mengimplementasikan IExtension<T>, Find mengembalikan salah satunya. Nilai yang dikembalikan dari FindAll adalah snapshot.

Ada dua skenario utama. Skenario pertama menggunakan properti Extensions sebagai kamus berbasis jenis untuk menyisipkan status pada objek untuk memungkinkan komponen lain mencarinya menggunakan jenis.

Skenario kedua menggunakan properti Attach dan Detach untuk memungkinkan objek berpartisipasi dalam perilaku kustom, seperti mendaftar untuk peristiwa, menonton transisi status, dan sebagainya.

Antarmuka IExtensionCollection<T> adalah kumpulan objek IExtension<T> yang memungkinkan pengambilan IExtension<T> berdasarkan jenisnya. IExtensionCollection<T>.Find mengembalikan objek yang paling baru ditambahkan yang merupakan IExtension<T> dari jenis tersebut.

Objek yang Dapat Diperluas di Windows Communication Foundation

Ada empat objek yang dapat diperluas di Windows Communication Foundation (WCF):

  • ServiceHostBase – Ini adalah kelas dasar untuk host layanan. Ekstensi kelas ini dapat digunakan untuk memperluas perilaku ServiceHostBase itu sendiri atau untuk menyimpan status untuk setiap layanan.

  • InstanceContext – Kelas ini menghubungkan instans jenis layanan dengan runtime layanan. Ini berisi informasi tentang instans serta referensi ke InstanceContext yang berisi ServiceHostBase. Ekstensi kelas ini dapat digunakan untuk memperluas perilaku InstanceContext atau untuk menyimpan status untuk setiap layanan.

  • OperationContext – Kelas ini mewakili informasi operasi yang dikumpulkan runtime untuk setiap operasi. Ini termasuk informasi seperti header pesan masuk, properti pesan masuk, identitas keamanan masuk, dan informasi lainnya. Ekstensi kelas ini dapat memperluas perilaku OperationContext atau menyimpan status untuk setiap operasi.

  • IContextChannel – Antarmuka ini memungkinkan inspeksi setiap status untuk saluran dan proksi yang dibangun oleh runtime WCF. Ekstensi kelas ini dapat memperluas perilaku IClientChannel atau dapat menggunakannya untuk menyimpan status untuk setiap saluran.

Contoh kode berikut menunjukkan penggunaan ekstensi sederhana untuk melacak objek InstanceContext.

using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Configuration;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Description;
using System.Text;

namespace Microsoft.WCF.Documentation
{
  public class MyInstanceContextInitializer : IInstanceContextInitializer
  {
    public void Initialize(InstanceContext instanceContext, Message message)
    {
      MyInstanceContextExtension extension = new MyInstanceContextExtension();

      //Add your custom InstanceContext extension that will let you associate state with this instancecontext
      instanceContext.Extensions.Add(extension);
    }
  }

  //Create an Extension that will attach to each InstanceContext and let it retrieve the Id or whatever state you want to associate
  public class MyInstanceContextExtension : IExtension<InstanceContext>
  {

    //Associate an Id with each Instance Created.
    String instanceId;

    public MyInstanceContextExtension()
    { this.instanceId = Guid.NewGuid().ToString(); }

    public String InstanceId
    {
      get
      { return this.instanceId; }
    }

    public void Attach(InstanceContext owner)
    {
      Console.WriteLine("Attached to new InstanceContext.");
    }

    public void Detach(InstanceContext owner)
    {
      Console.WriteLine("Detached from InstanceContext.");
    }
  }

  public class InstanceInitializerBehavior : IEndpointBehavior
  {

    public void AddBindingParameters(ServiceEndpoint serviceEndpoint, BindingParameterCollection bindingParameters)
    {    }

    //Apply the custom IInstanceContextProvider to the EndpointDispatcher.DispatchRuntime
    public void ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint, EndpointDispatcher endpointDispatcher)
    {
      MyInstanceContextInitializer extension = new MyInstanceContextInitializer();
      endpointDispatcher.DispatchRuntime.InstanceContextInitializers.Add(extension);
    }

    public void ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime behavior)
    {    }

    public void Validate(ServiceEndpoint endpoint)
    {    }
  }

  public class InstanceInitializerBehaviorExtensionElement : BehaviorExtensionElement
  {

    public override Type BehaviorType
    {
      get { return typeof(InstanceInitializerBehavior); }
    }

    protected override object CreateBehavior()
    {
      return new InstanceInitializerBehavior();
    }
  }
}

Lihat juga