【发布时间】:2011-11-17 20:54:58
【问题描述】:
这是一个相当长的问题,所以提前感谢所有放弃时间阅读并评论/回答的人:)
编辑
- 此问题已大大简化。
- 示例代码现在是一个完整、简单的程序
我正在使用通过接口实现的观察者模式:
public interface IObserver<in T>where T:EventArgs
{
void Update(object sender, T e);
}
public interface ISubject<in T, TU>where TU:EventArgs
{
event EventHandler<TU> Notify;
T State { set; }
void Attach(Action<object,TU> callback);
void Detach(Action<object, TU> callback);
}
我创建了两个实现这些接口的简单类
当MySubject 对象中引发Notify 事件时,MyObserver 对象将简单地向控制台窗口输出一个字符串。
public class MyObserver:IObserver<TestEventArgs>
{
private ISubject<bool, TestEventArgs> _subject;
public MyObserver(ISubject<bool, TestEventArgs> subject)
{
_subject = subject;
}
public void Subscribe()
{
_subject.Attach(Update);
}
public void Unsubscribe()
{
_subject.Detach(Update);
}
public void Update(object sender, TestEventArgs e)
{
Console.WriteLine(e.TestMessage);
}
}
public class MySubject:ISubject<bool, TestEventArgs>
{
public void ObservableEvent(string message)
{
InvokeNotify(message);
}
private void InvokeNotify(string message)
{
EventHandler<TestEventArgs> handler = Notify;
if(handler != null)
{
handler(this, new TestEventArgs(message));
}
}
public event EventHandler<TestEventArgs> Notify;
public bool State
{
set { throw new NotImplementedException(); }
}
public void Attach(Action<object, TestEventArgs> callback)
{
Notify += new EventHandler<TestEventArgs>(callback);
}
public void Detach(Action<object, TestEventArgs> callback)
{
Notify -= new EventHandler<TestEventArgs>(callback);
}
}
public class TestEventArgs:EventArgs
{
public TestEventArgs(string message)
{
TestMessage = message;
}
public string TestMessage { get; private set; }
}
这个测试程序表明:
- 在
myObserver订阅事件之前,没有消息输出到控制台窗口。 - 在
myObserver订阅Notify事件后,消息将输出到控制台窗口。 -
在
myObserver取消订阅Notify事件后,消息仍会输出到控制台窗口static void Main(string[] args) { MySubject mySubject = new MySubject(); MyObserver myObserver = new MyObserver(mySubject); //we have not subscribed to the event so this should not be output to the console mySubject.ObservableEvent("First Test"); myObserver.Subscribe(); //we are now subscribing to the event. This should be displayed on the console window mySubject.ObservableEvent("Second Test"); myObserver.Unsubscribe(); //We have unsubscribed from the event. I would not expect this to be displayed //...but it is! mySubject.ObservableEvent("Third Test"); Console.ReadLine(); }
我遇到的问题是取消订阅过程不起作用。
我真的不明白为什么。
问题
- 为什么取消订阅过程不起作用?
- 比较 2 个事件处理程序时会发生什么?它们如何定义为相等或不相等?这可能会导致为什么调用列表
Contains方法总是返回false的答案。
【问题讨论】:
-
嗯....NET 框架已经实现了观察者模式。你为什么要在这里做一个新的轮子?作业?
-
这里有很多 代码。请尝试制作一个简短但完整的程序来演示问题,而不是所有周围的包袱。
-
@Brian:我想知道同样的事情并没有问它,因为我没有阅读整个问题并且可能错过了一些东西。无论如何,.NET 中的事件是观察者模式的实现,所以基本上,你 Lewray 使用观察者模式的一种实现来实现另一种?
-
@Brian - Fair Point,我想在有了这个想法之后,我对自己实现它有点忘乎所以,并没有考虑检查是否存在现有实现。我对 C# 和 .Net 并不完全陌生,但仍有很多东西要学! - 但是在查看 .NET IObservable
...为什么有订阅方法,但没有取消订阅? -
@Jon - 我知道,有很多包袱。我会看看我是否可以在更简单的环境中复制并将结果作为编辑或其他内容发布。
标签: c# events .net-4.0 observer-pattern unsubscribe