Fut*_*ist 5 .net c# collections events delegates
我认为这是一个简单的"问题",我已经找到了几个解决方案,但我不知道哪种方式可以用于C#中的最佳实践.
在应用程序的生命周期中,我有一个主对象(比如一个单例).这个"MasterClass"创建了一堆新类型的对象,每次调用MasterClass.Instance.CreateSlaveObject时都说"SlaveClass".
此MasterClass还监视其他一些对象的状态更改,当发生这种情况时,通知它创建的SlaveClass对象的更改.看起来很简单.
因为我来自本地C++世界,所以我首先使用它来创建一个接口
Interface IChangeEventListener
{
void ChangeHappened();
}
Run Code Online (Sandbox Code Playgroud)
我从中派生出"SlaveClass".然后在我的"MasterClass"中,我有:
...
IList<IChangeEventListener> slaveList;
...
CreateSlaveObject
{
...
slaveList.Add(slave);
}
...
ChangeHappened()
{
...
foreach(var slave in slaveList)
{
slave.ChangeHappened();
}
}
Run Code Online (Sandbox Code Playgroud)
这很有效.但是我一直在想,如果有另一种(更好的)方法可以做到这一点.所以我对这个主题进行了更多研究,并看到了C#事件.
因此,我不是在MasterClass中维护一个奴隶集合,而是将MasterClass注入到SlaveClass的ctor中(或通过一个属性),让SlaveClass对象将它的ChangeHappened作为事件处理程序添加.这将说明:
...Master...
public delegate void ChangeHappenedDelegate(object sender, NewsInfoArgs args);
public event NewUpdateDelegate ChangeHappenedEvent;
....
public SlaveClass (MasterClass publisher) //inject publisher service
{
publisher.ChangeHappenedEvent += ChangeHappened;
}
Run Code Online (Sandbox Code Playgroud)
但这似乎是Slave和Master之间不必要的耦合,但我喜欢所提供的内置事件通知机制的优雅.
那么我应该保留当前的代码,还是转向基于事件的方法(使用发布者注入)?为什么?
或者,如果您可以提出我可能错过的替代解决方案,我也会感激.
嗯,在我看来,像你所展示的事件和界面是同一枚硬币的两面(至少在你所描述的背景下),但它们实际上是两面.
我对事件的看法是"我需要订阅你的活动,因为我需要你在发生事情时告诉我".
接口的方式是"我需要在你身上调用一种方法来告诉你我发生了什么事".
它听起来可能是一样的,但它在说话的人不同,在这两种情况下,它都是你正在谈论的"大师班",而这一切都有所不同.
请注意,如果您的从属类有一个适合在主类中发生某些事情时调用的方法,那么您不需要包含代码来挂起它,您可以轻松地在您的类中执行此操作. CreateSlaveClass方法:
SlaveClass sc = new SlaveClass();
ChangeHappenedEvent += sc.ChangeHappened;
return sc;
Run Code Online (Sandbox Code Playgroud)
这基本上将使用事件系统,但让MasterClass代码完成事件的所有连接.
SlaveClass对象是否与单例类一样长寿?如果没有,那么你需要处理它们变得陈旧/不再需要的情况,如上面的情况(基本上在你和我的两个中),你在MasterClass中持有对那些对象的引用,因此它们除非您强行删除这些事件或取消注册接口,否则永远不会有资格进行垃圾回收.
为了解决SlaveClass与MasterClass不同的问题,你将遇到同样的耦合问题,正如你在评论中所指出的那样.
"处理"(注意引号)的一种方法可能是没有真正直接链接到SlaveClass对象上的正确方法,而是创建一个内部将调用此方法的包装器对象.这样做的好处是包装器对象可以在内部使用WeakReference对象,这样一旦你的SlaveClass对象有资格进行垃圾收集,就可以收集它,然后下次你尝试在它上面调用正确的方法时,你会注意到这一点,因此你必须清理.
例如,像这样(在这里我输入没有Visual Studio intellisense和编译器的好处,请采用此代码的含义,而不是语法(错误).)
public class WrapperClass
{
private WeakReference _Slave;
public WrapperClass(SlaveClass slave)
{
_Slave = new WeakReference(slave);
}
public WrapperClass.ChangeHappened()
{
Object o = _Slave.Target;
if (o != null)
((SlaveClass)o).ChangeHappened();
else
MasterClass.ChangeHappenedEvent -= ChangeHappened;
}
}
Run Code Online (Sandbox Code Playgroud)
在你的MasterClass中,你会这样做:
SlaveClass sc = new SlaveClass();
WrapperClass wc = new WrapperClass(sc);
ChangeHappenedEvent += wc.ChangeHappened;
return sc;
Run Code Online (Sandbox Code Playgroud)
收集SlaveClass对象后,从MasterClass到事件处理程序的下一次调用(但不会早于此事件)通知它们更改,所有那些不再有对象的包装器将被删除.
| 归档时间: |
|
| 查看次数: |
2750 次 |
| 最近记录: |