c#4观察员实施

时间:2010-09-07 01:31:33

标签: design-patterns c#-4.0

我想要一个按钮,当按下它时,文本框中会显示一个新字符串

我做错了什么

有人可以告诉我为什么这段代码不起作用? ......

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public event Startdelegate StartEvent;
        myButton button;
        newTb[] tb;
        public Form1()
        {
            InitializeComponent();

            button = new myButton();
            button.Parent = this;
            button.Location = new Point(120, 0);
            button.Text = "click on me!!!";
            tb = new newTb[8];

            for (int i = 0; i <= 80; i += 15)
            {
                tb[i / 15] = new newTb();
                tb[i / 15].Parent = this;
                tb[i / 15].Location = new Point(i + i, i + i);
               // button.Subscribe(tb[i / 15]);
            }

            button.Click += new EventHandler(button_Click);

        }
        private void button_Click(object sender, EventArgs e)
        {
            button.s = "this is clicking";
            //button.Notify();
        }
    }

    public class myButton : Button, IObservable<newTb>
    {
        public string s;
        private List<IObserver<newTb>> observers;

        public myButton()
        {
            observers = new List<IObserver<newTb>>();
        }

        public IDisposable Subscribe(IObserver<newTb> observer)
        {
            if (!observers.Contains(observer))
            {
                observers.Add(observer);           
            }
            return new Unsubscriber(observers, observer);  
        }

        protected void Notify(newTb tb)
        {
            foreach (IObserver<newTb> observer in observers)
            {
                observer.OnNext(tb);
            }
        }

        #region Unsubscriber
        private class Unsubscriber : IDisposable
        {
            private List<IObserver<newTb>> observers;
            private IObserver<newTb> observer;

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

            public void Dispose()
            {
                if (observer != null && observers.Contains(observer))
                {
                    observers.Remove(observer);
                }
            }
        }
        #endregion 

        class newTb : TextBox, IObserver<string>
        {
            string s;
            public void OnCompleted() { }
            public void OnError(Exception error) { }
            public void OnNext(string value)
            {
                this.Text = value;
            }
        }
    }
}

2 个答案:

答案 0 :(得分:5)

根据http://msdn.microsoft.com/en-us/library/dd783449.aspx

IObserver和IObservable接口为基于推送的通知提供了一种通用机制,  也称为观察者设计模式。 IObservable接口表示发送通知的类(提供者);  IObserver接口表示接收它们的类(观察者)。

T代表提供通知信息的类。

在您的情况下,您传递的信息是一条消息(字符串)。 在您的示例中,您传递了控件newTB

使用以下声明

   public class ObservableButton : Button,  IObservable<string>   {}
   public class ObserverTextBox  : TextBox, IObserver<string>     {}

每件事都落到了地方。

可以用这种方式编写classObservableButton的Notify方法。

    public void Notify(string text)
    {
        foreach (IObserver<string> observer in _Observers)
        {                
            observer.OnNext(text);
        }
    }

这里是完整的源代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ObservableDemo
{
    public class ObservableButton : Button, IObservable<string>
    {
        private List<IObserver<string>> _Observers;

        public ObservableButton()
        {
            _Observers = new List<IObserver<string>>();
        }
        IDisposable IObservable<string>.Subscribe(IObserver<string> observer)
        {
            if (!_Observers.Contains(observer))
            {
                _Observers.Add(observer);
            }
            return new Unsubscriber(_Observers, observer);
        }
        public void Notify(string text)
        {
            foreach (IObserver<string> observer in _Observers)
            {                
                observer.OnNext(text);
            }
        }
        private class Unsubscriber : IDisposable
        {
            private List<IObserver<string>>     observers;
            private IObserver<string>           observer;

            public Unsubscriber(List<IObserver<string>> observers, IObserver<string> observer)
            {
                this.observers = observers;
                this.observer  = observer;
            }
            public void Dispose()
            {
                if (observer != null && observers.Contains(observer))
                {
                    observers.Remove(observer);
                }
            }
        }
    }
}

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ObservableDemo
{    
    public class ObserverTextBox : TextBox,  IObserver<string>
    {
        private IDisposable unsubscriber;

        void IObserver<string>.OnCompleted()
        {
        }
        void IObserver<string>.OnError(Exception error)
        {

        }
        void IObserver<string>.OnNext(string value)
        {
            this.Text = value;
            this.Refresh();
        }
        public virtual void Subscribe(IObservable<string> provider)
        {
            if (provider != null)
                unsubscriber = provider.Subscribe(this);
        }
        public virtual void Unsubscribe()
        {
            unsubscriber.Dispose();
        }
    }    
}

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ObservableDemo
{
    public partial class Form1 : Form
    {
        ObservableButton button;

        public Form1()
        {
            InitializeComponent();

            button          = new ObservableButton();
            button.Parent   = this;
            button.Location = new Point(120, 0);
            button.Text     = "click on me!!!";
            button.Click   += new EventHandler(button_Click);

            for (int i = 0; i < 8; i++)
            {
                ObserverTextBox tb  = new ObserverTextBox();
                tb.Parent           = this;
                tb.Location         = new Point(0 , 30+(i*30));
                tb.Width            = 300;
                tb.Subscribe(button);
            }
        }
        private void button_Click(object sender, EventArgs e)
        {
            button.Notify(String.Format("{0} this is the message", DateTime.Now));
        }
        void Form1_Load(object sender, System.EventArgs e)
        {
        }
    }
}

答案 1 :(得分:1)

我相信这可能是你的问题:

class newTb : TextBox, IObserver<string>

因为基于这个样本你想要观察的是什么:

observers = new List<IObserver<newTb>>();

实际上是IObserver&lt; newTb&gt;,它与IObserver&lt; string&gt;的类型不同。你的newTb类没有实现第一个接口,它只实现了后者。不知道为什么这会编译(如果确实如此)。