Nasıl yapılır: Sağlayıcıyı Uygulama

Gözlemci tasarım düzeni, verileri izleyen ve bildirim gönderen bir sağlayıcı ile sağlayıcıdan bildirim (geri çağırma) alan bir veya daha fazla gözlemci arasında bir bölme gerektirir. Bu konu başlığında sağlayıcı oluşturma adımları anlatılmaktadır. nasıl yapılır: Gözlemci Uygulama ile ilgili bir konu başlığında gözlemcinin nasıl oluşturulacağı ele alınmaktadır.

Sağlayıcı oluşturmak için

  1. Sağlayıcının gözlemcilere göndermekle sorumlu olduğu verileri tanımlayın. Sağlayıcı ve gözlemcilere gönderdiği veriler tek bir tür olsa da, bunlar genellikle farklı türlerle temsil edilir. Örneğin, bir sıcaklık izleme uygulamasında Temperature , yapı sağlayıcının (sonraki adımda tanımlanan sınıf tarafından TemperatureMonitor temsil edilir) izlediği ve hangi gözlemcilerin abone olduğu verileri tanımlar.

    using System;
    
    public struct Temperature
    {
       private decimal temp;
       private DateTime tempDate;
    
       public Temperature(decimal temperature, DateTime dateAndTime)
       {
          this.temp = temperature;
          this.tempDate = dateAndTime;
       }
    
       public decimal Degrees
       { get { return this.temp; } }
    
       public DateTime Date
       { get { return this.tempDate; } }
    }
    
    Public Structure Temperature
        Private temp As Decimal
        Private tempDate As DateTime
    
        Public Sub New(ByVal temperature As Decimal, ByVal dateAndTime As DateTime)
            Me.temp = temperature
            Me.tempDate = dateAndTime
        End Sub
    
        Public ReadOnly Property Degrees As Decimal
            Get
                Return Me.temp
            End Get
        End Property
    
        Public ReadOnly Property [Date] As DateTime
            Get
                Return tempDate
            End Get
        End Property
    End Structure
    
  2. Arabirimi uygulayan bir tür olan veri sağlayıcısını System.IObservable<T> tanımlayın. Sağlayıcının genel tür bağımsız değişkeni, sağlayıcının gözlemcilere gönderdiği türdür. Aşağıdaki örnek, genel tür bağımsız değişkeniyle Temperatureoluşturulmuş System.IObservable<T> bir uygulama olan sınıfını tanımlarTemperatureMonitor.

    using System;
    using System.Collections.Generic;
    
    public class TemperatureMonitor : IObservable<Temperature>
    {
    
    Imports System.Collections.Generic
    
    
    Public Class TemperatureMonitor : Implements IObservable(Of Temperature)
    
  3. Sağlayıcının, her gözlemcinin uygun olduğunda bilgilendirilebilmeleri için gözlemcilere yönelik başvuruları nasıl depolayacaklarını belirleyin. En yaygın olarak, genel nesne gibi bir List<T> koleksiyon nesnesi bu amaç için kullanılır. Aşağıdaki örnek, sınıf oluşturucusunda TemperatureMonitor örneği oluşturulmuş özel List<T> bir nesneyi tanımlar.

    using System;
    using System.Collections.Generic;
    
    public class TemperatureMonitor : IObservable<Temperature>
    {
       List<IObserver<Temperature>> observers;
    
       public TemperatureMonitor()
       {
          observers = new List<IObserver<Temperature>>();
       }
    
    Imports System.Collections.Generic
    
    
    Public Class TemperatureMonitor : Implements IObservable(Of Temperature)
        Dim observers As List(Of IObserver(Of Temperature))
    
        Public Sub New()
            observers = New List(Of IObserver(Of Temperature))
        End Sub
    
  4. Sağlayıcının abonelere geri dönebileceği, böylece istedikleri zaman bildirim almayı durdurabilecekleri bir IDisposable uygulama tanımlayın. Aşağıdaki örnek, sınıf örneği oluşturulurken abone koleksiyonuna ve aboneye bir başvuru geçirilen iç içe Unsubscriber geçmiş bir sınıfı tanımlar. Bu kod, abonenin kendisini abone koleksiyonundan kaldırmak için nesnesinin IDisposable.Dispose uygulamasını çağırmasını sağlar.

    private class Unsubscriber : IDisposable
    {
       private List<IObserver<Temperature>> _observers;
       private IObserver<Temperature> _observer;
    
       public Unsubscriber(List<IObserver<Temperature>> observers, IObserver<Temperature> observer)
       {
          this._observers = observers;
          this._observer = observer;
       }
    
       public void Dispose()
       {
          if (! (_observer == null)) _observers.Remove(_observer);
       }
    }
    
    Private Class Unsubscriber : Implements IDisposable
        Private _observers As List(Of IObserver(Of Temperature))
        Private _observer As IObserver(Of Temperature)
    
        Public Sub New(ByVal observers As List(Of IObserver(Of Temperature)), ByVal observer As IObserver(Of Temperature))
            Me._observers = observers
            Me._observer = observer
        End Sub
    
        Public Sub Dispose() Implements IDisposable.Dispose
            If _observer IsNot Nothing Then _observers.Remove(_observer)
        End Sub
    End Class
    
  5. IObservable<T>.Subscribe yöntemini uygulayın. yöntemine arabirim başvurusu System.IObserver<T> geçirilir ve 3. adımda bu amaç için tasarlanmış nesnede depolanmalıdır. Yöntemi daha sonra 4. adımda geliştirilen uygulamayı döndürmelidir IDisposable . Aşağıdaki örnekte sınıfındaki yönteminin Subscribe uygulanması gösterilmektedir TemperatureMonitor .

    public IDisposable Subscribe(IObserver<Temperature> observer)
    {
       if (! observers.Contains(observer))
          observers.Add(observer);
    
       return new Unsubscriber(observers, observer);
    }
    
    Public Function Subscribe(ByVal observer As System.IObserver(Of Temperature)) As System.IDisposable Implements System.IObservable(Of Temperature).Subscribe
        If Not observers.Contains(observer) Then
            observers.Add(observer)
        End If
        Return New Unsubscriber(observers, observer)
    End Function
    
  6. , IObserver<T>.OnErrorve IObserver<T>.OnCompleted uygulamalarını çağırarak IObserver<T>.OnNextgözlemcileri uygun şekilde bilgilendirin. Bazı durumlarda, bir sağlayıcı bir hata oluştuğunda OnError yöntemini çağıramayabilir. Örneğin aşağıdaki GetTemperature yöntem, sıcaklık verilerini beş saniyede bir okuyan ve önceki okumadan bu yana sıcaklığın en az .1 derece değiştiğinde gözlemcilere bildirimde bulunan bir monitörün simülasyonunu yapar. Cihaz bir sıcaklık bildirmezse (yani değeri null ise), sağlayıcı gözlemcilere iletimin tamamlandığını bildirir. Her gözlemcinin OnCompleted yöntemini çağırmaya ek olarak yönteminin GetTemperature koleksiyonu temizlediğini List<T> unutmayın. Bu durumda sağlayıcı, gözlemcilerinin yöntemine OnError hiçbir çağrı yapmaz.

    public void GetTemperature()
    {
       // Create an array of sample data to mimic a temperature device.
       Nullable<Decimal>[] temps = {14.6m, 14.65m, 14.7m, 14.9m, 14.9m, 15.2m, 15.25m, 15.2m,
                                    15.4m, 15.45m, null };
       // Store the previous temperature, so notification is only sent after at least .1 change.
       Nullable<Decimal> previous = null;
       bool start = true;
    
       foreach (var temp in temps) {
          System.Threading.Thread.Sleep(2500);
          if (temp.HasValue) {
             if (start || (Math.Abs(temp.Value - previous.Value) >= 0.1m )) {
                Temperature tempData = new Temperature(temp.Value, DateTime.Now);
                foreach (var observer in observers)
                   observer.OnNext(tempData);
                previous = temp;
                if (start) start = false;
             }
          }
          else {
             foreach (var observer in observers.ToArray())
                if (observer != null) observer.OnCompleted();
    
             observers.Clear();
             break;
          }
       }
    }
    
    Public Sub GetTemperature()
        ' Create an array of sample data to mimic a temperature device.
        Dim temps() As Nullable(Of Decimal) = {14.6D, 14.65D, 14.7D, 14.9D, 14.9D, 15.2D, 15.25D, 15.2D,
                                              15.4D, 15.45D, Nothing}
        ' Store the previous temperature, so notification is only sent after at least .1 change.
        Dim previous As Nullable(Of Decimal)
        Dim start As Boolean = True
    
        For Each temp In temps
            System.Threading.Thread.Sleep(2500)
    
            If temp.HasValue Then
                If start OrElse Math.Abs(temp.Value - previous.Value) >= 0.1 Then
                    Dim tempData As New Temperature(temp.Value, Date.Now)
                    For Each observer In observers
                        observer.OnNext(tempData)
                    Next
                    previous = temp
                    If start Then start = False
                End If
            Else
                For Each observer In observers.ToArray()
                    If observer IsNot Nothing Then observer.OnCompleted()
                Next
                observers.Clear()
                Exit For
            End If
        Next
    End Sub
    

Örnek

Aşağıdaki örnek, bir sıcaklık izleme uygulaması için bir IObservable<T> uygulama tanımlamaya yönelik tam kaynak kodunu içerir. Gözlemcilere Temperature gönderilen veriler olan yapıyı ve TemperatureMonitor uygulama olan sınıfı içerir IObservable<T> .

using System.Threading;
using System;
using System.Collections.Generic;

public class TemperatureMonitor : IObservable<Temperature>
{
   List<IObserver<Temperature>> observers;

   public TemperatureMonitor()
   {
      observers = new List<IObserver<Temperature>>();
   }

   private class Unsubscriber : IDisposable
   {
      private List<IObserver<Temperature>> _observers;
      private IObserver<Temperature> _observer;

      public Unsubscriber(List<IObserver<Temperature>> observers, IObserver<Temperature> observer)
      {
         this._observers = observers;
         this._observer = observer;
      }

      public void Dispose()
      {
         if (! (_observer == null)) _observers.Remove(_observer);
      }
   }

   public IDisposable Subscribe(IObserver<Temperature> observer)
   {
      if (! observers.Contains(observer))
         observers.Add(observer);

      return new Unsubscriber(observers, observer);
   }

   public void GetTemperature()
   {
      // Create an array of sample data to mimic a temperature device.
      Nullable<Decimal>[] temps = {14.6m, 14.65m, 14.7m, 14.9m, 14.9m, 15.2m, 15.25m, 15.2m,
                                   15.4m, 15.45m, null };
      // Store the previous temperature, so notification is only sent after at least .1 change.
      Nullable<Decimal> previous = null;
      bool start = true;

      foreach (var temp in temps) {
         System.Threading.Thread.Sleep(2500);
         if (temp.HasValue) {
            if (start || (Math.Abs(temp.Value - previous.Value) >= 0.1m )) {
               Temperature tempData = new Temperature(temp.Value, DateTime.Now);
               foreach (var observer in observers)
                  observer.OnNext(tempData);
               previous = temp;
               if (start) start = false;
            }
         }
         else {
            foreach (var observer in observers.ToArray())
               if (observer != null) observer.OnCompleted();

            observers.Clear();
            break;
         }
      }
   }
}
Imports System.Threading
Imports System.Collections.Generic


Public Class TemperatureMonitor : Implements IObservable(Of Temperature)
    Dim observers As List(Of IObserver(Of Temperature))

    Public Sub New()
        observers = New List(Of IObserver(Of Temperature))
    End Sub

    Private Class Unsubscriber : Implements IDisposable
        Private _observers As List(Of IObserver(Of Temperature))
        Private _observer As IObserver(Of Temperature)

        Public Sub New(ByVal observers As List(Of IObserver(Of Temperature)), ByVal observer As IObserver(Of Temperature))
            Me._observers = observers
            Me._observer = observer
        End Sub

        Public Sub Dispose() Implements IDisposable.Dispose
            If _observer IsNot Nothing Then _observers.Remove(_observer)
        End Sub
    End Class

    Public Function Subscribe(ByVal observer As System.IObserver(Of Temperature)) As System.IDisposable Implements System.IObservable(Of Temperature).Subscribe
        If Not observers.Contains(observer) Then
            observers.Add(observer)
        End If
        Return New Unsubscriber(observers, observer)
    End Function

    Public Sub GetTemperature()
        ' Create an array of sample data to mimic a temperature device.
        Dim temps() As Nullable(Of Decimal) = {14.6D, 14.65D, 14.7D, 14.9D, 14.9D, 15.2D, 15.25D, 15.2D,
                                              15.4D, 15.45D, Nothing}
        ' Store the previous temperature, so notification is only sent after at least .1 change.
        Dim previous As Nullable(Of Decimal)
        Dim start As Boolean = True

        For Each temp In temps
            System.Threading.Thread.Sleep(2500)

            If temp.HasValue Then
                If start OrElse Math.Abs(temp.Value - previous.Value) >= 0.1 Then
                    Dim tempData As New Temperature(temp.Value, Date.Now)
                    For Each observer In observers
                        observer.OnNext(tempData)
                    Next
                    previous = temp
                    If start Then start = False
                End If
            Else
                For Each observer In observers.ToArray()
                    If observer IsNot Nothing Then observer.OnCompleted()
                Next
                observers.Clear()
                Exit For
            End If
        Next
    End Sub
End Class

Ayrıca bkz.