143 votes

Exemple super-simple de c# observateur/observable avec des délégués

J’ai récemment commencé à creuser en c#, mais je ne peux pas par ma vie comprendre comment les délégués travaillent lors de l’implémentation du modèle de l’observateur/observable dans la langue.

Quelqu'un pourrait-il me donner un exemple très simple de comment c’est fait ? J’ai googlé, mais tous les exemples que j’ai trouvé étaient trop axée sur le problème ou trop « gonflé ».

227voto

Jon Skeet Points 692016

Le modèle d'observateur est généralement mis en œuvre avec des événements .

Voici un exemple:

 using System;

class Observable
{
    public event EventHandler SomethingHappened;

    public void DoSomething()
    {
        EventHandler handler = SomethingHappened;
        if (handler != null)
        {
            handler(this, EventArgs.Empty);
        }
    }
}

class Observer
{
    public void HandleEvent(object sender, EventArgs args)
    {
        Console.WriteLine("Something happened to " + sender);
    }
}

class Test
{
    static void Main()
    {
        Observable observable = new Observable();
        Observer observer = new Observer();
        observable.SomethingHappened += observer.HandleEvent;

        observable.DoSomething();
    }
}
 

Voir l'article lié pour plus de détails.

15voto

Lasse V. Karlsen Points 148037

Voici un exemple simple:

public class ObservableClass
{
    private Int32 _Value;

    public Int32 Value
    {
        get { return _Value; }
        set
        {
            if (_Value != value)
            {
                _Value = value;
                OnValueChanged();
            }
        }
    }

    public event EventHandler ValueChanged;

    protected void OnValueChanged()
    {
        if (ValueChanged != null)
            ValueChanged(this, EventArgs.Empty);
    }
}

public class ObserverClass
{
    public ObserverClass(ObservableClass observable)
    {
        observable.ValueChanged += TheValueChanged;
    }

    private void TheValueChanged(Object sender, EventArgs e)
    {
        Console.Out.WriteLine("Value changed to " +
            ((ObservableClass)sender).Value);
    }
}

public class Program
{
    public static void Main()
    {
        ObservableClass observable = new ObservableClass();
        ObserverClass observer = new ObserverClass(observable);
        observable.Value = 10;
    }
}

Note:

  • Cela viole une règle que je n'ai pas décrocher l'observateur de l'observable, c'est peut-être assez bon pour cet exemple simple, mais assurez-vous de ne pas garder les observateurs accroché à vos événements comme ça. Une façon de résoudre ce problème serait de faire ObserverClass IDisposable, et de laisser les .Disposer méthode de faire l'opposé de ce code dans le constructeur
  • Pas d'erreur de vérification effectuée, au moins un null-chèque doit être fait dans le constructeur de la ObserverClass

5voto

Ray Points 1527

Vérifier cette introduction au cadre de Rx qui utilise merveilleux asynchrone IObserver-IObservable non bloquante, modèle http://themechanicalbride.blogspot.com/2009/07/introducing-rx-linq-to-events.html de programmation

5voto

Jesse C. Slicer Points 11750

J'ai lié un couple de grands exemples ci-dessus (merci comme toujours pour M. Skeet et M. Karlsen) pour inclure un couple de différentes Observables et utilisé une interface pour garder une trace d'eux dans l'Observateur et a permis à l'Observateur de "d'observer" un certain nombre de phénomènes Observables par l'intermédiaire d'une liste interne:

namespace ObservablePattern
{
    using System;
    using System.Collections.Generic;

    internal static class Program
    {
        private static void Main()
        {
            var observable = new Observable();
            var anotherObservable = new AnotherObservable();

            using (IObserver observer = new Observer(observable))
            {
                observable.DoSomething();
                observer.Add(anotherObservable);
                anotherObservable.DoSomething();
            }

            Console.ReadLine();
        }
    }

    internal interface IObservable
    {
        event EventHandler SomethingHappened;
    }

    internal sealed class Observable : IObservable
    {
        public event EventHandler SomethingHappened;

        public void DoSomething()
        {
            var handler = this.SomethingHappened;

            Console.WriteLine("About to do something.");
            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }
        }
    }

    internal sealed class AnotherObservable : IObservable
    {
        public event EventHandler SomethingHappened;

        public void DoSomething()
        {
            var handler = this.SomethingHappened;

            Console.WriteLine("About to do something different.");
            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }
        }
    }

    internal interface IObserver : IDisposable
    {
        void Add(IObservable observable);

        void Remove(IObservable observable);
    }

    internal sealed class Observer : IObserver
    {
        private readonly Lazy<IList<IObservable>> observables =
            new Lazy<IList<IObservable>>(() => new List<IObservable>());

        public Observer()
        {
        }

        public Observer(IObservable observable) : this()
        {
            this.Add(observable);
        }

        public void Add(IObservable observable)
        {
            if (observable == null)
            {
                return;
            }

            lock (this.observables)
            {
                this.observables.Value.Add(observable);
                observable.SomethingHappened += HandleEvent;
            }
        }

        public void Remove(IObservable observable)
        {
            if (observable == null)
            {
                return;
            }

            lock (this.observables)
            {
                observable.SomethingHappened -= HandleEvent;
                this.observables.Value.Remove(observable);
            }
        }

        public void Dispose()
        {
            for (var i = this.observables.Value.Count - 1; i >= 0; i--)
            {
                this.Remove(this.observables.Value[i]);
            }
        }

        private static void HandleEvent(object sender, EventArgs args)
        {
            Console.WriteLine("Something happened to " + sender);
        }
    }
}

0voto

Imran Rizvi Points 2886

Je did ' t voulez changer mon code source pour ajouter des observateurs supplémentaires, donc j’ai écrit l’exemple simple suivant :

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X