C#::何时使用从事件处理接口衍生事件或对象的集合? [英] C#:: When to use events or a collection of objects derived from an event handling Interface?

查看:104
本文介绍了C#::何时使用从事件处理接口衍生事件或对象的集合?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有什么,我认为这是一个简单的问题,而我已经找到了几个解决方案,但我不知道该何去何从ANDN C#中的最佳实践。

I have what I think is a simple "problem" to which I have found a couple of solutions but I am not sure which way to go andn the best practice in C#.

我有一个主对象(比如单身)的应用程序的生命周期中实例化一次。这个大师班创造了许多新类型的对象,说SlaveClass每个MasterClass.Instance.CreateSlaveObject被调用的时候。

I have a master object (say a singleton) instanciated once during the lifespan of the application. This "MasterClass" creates a bunch of new type of objects, say "SlaveClass" every time MasterClass.Instance.CreateSlaveObject is called.

这个大师班还可以监视其他对象的状态变化,当这种情况发生,通知SlaveClass对象,它创造了变化。似乎很简单。

This MasterClass also monitors some other object for status change, and when that happens, notifies the SlaveClass objects it created of the change. Seems simple enough.

由于我来自本地C ++的世界里,我第一次做它的方式,它有一个接口

Since I come from the native C++ world, the way I did it first it to have an interface

Interface IChangeEventListener
{
    void ChangeHappened();
}

我从中派生出来的SlaveClass。然后在我的大师班我有:

from which I derived "SlaveClass". Then in my "MasterClass" i have:

...
IList<IChangeEventListener> slaveList;
...
CreateSlaveObject
{
    ...
    slaveList.Add(slave);
}
...
ChangeHappened()
{
    ...
    foreach(var slave in slaveList)
    {
       slave.ChangeHappened();
    }
}

和工作原理。但我一直在我的脑海里不知道是否有这样做的另一个(更好)的方式。于是我研究了一下更多的话题,看到了C#的活动。

And this works. But I kept wondering in the back of my mind if there is another (better) way of doing this. So I researched a bit more on the topic and saw the C# events.

因此​​,而不是维持在大师班奴的集合,我就基本上大师班注入SlaveClass的构造函数(或通过一个属性),让SlaveClass对象添加它ChangeHappened作为事件处理程序。这将加以说明:

So instead of maintaining a collection of slaves in the MasterClass, I would basically inject the MasterClass into the ctor of SlaveClass (or via a property) and let the SlaveClass object add it's ChangeHappened as an event handler. this would be illustrated:

  ...Master...          
  public delegate void ChangeHappenedDelegate(object sender, NewsInfoArgs args);
  public event NewUpdateDelegate ChangeHappenedEvent;
  ....

  public SlaveClass (MasterClass publisher) //inject publisher service
  {
      publisher.ChangeHappenedEvent += ChangeHappened;
  }

不过,这似乎是像奴隶和法师之间的非必要耦合,但我喜欢提供内置的事件通知机制的风采。

But this seems to be like an un-necessary coupling between the Slave and the Master, but I like the elegance of the provided build-in event notification mechanism.

所以,我应该保持我目前的code,或移动到基于事件的方法(与出版商注射)?为什么?

So should I keep my current code, or move to the event based approach (with publisher injection)? and why?

或者,如果你能提出一个替代解决方案,我可能会错过,我会AP preciate这一点。

Or if you can propose an alternative solution I might have missed, I would appreciate that as well.

推荐答案

嗯,在我的脑海里,事件和接口,如您显示是同一枚硬币(至少在你描述它的上下文中)的两面,但他们再实际上是两个的双方的这一点。

Well, in my mind, events and interfaces like you showed are two sides of the same coin (at least in the context you described it), but they're really two sides of this.

我认为有关事件的方式是,我要订阅你的事件,因为我需要你告诉我,当事情发生在你身上。

The way I think about events is that "I need to subscribe to your event because I need you to tell me when something happens to you".

而界面的方法是:我需要调用一个方法,你要告诉你的东西发生在我身上。

Whereas the interface way is "I need to call a method on you to inform you that something happened to me".

这听起来就像是相同的,但它的不同之处是谁说话,在这两种情况下,你的大师班,也就是讲,这使得所有的差异。

It can sound like the same, but it differs in who is talking, in both cases it is your "masterclass" that is talking, and that makes all the difference.

请注意,如果你的奴隶类有一个可用的方法,这将是适合调用时事情发生在你的大师班,你不需要奴隶阶级遏制code勾这件事,你可以在CreateSlaveClass方法很容易做到这一点:

Note that if your slave classes have a method available that would be suitable for calling when something happened in your master class, you don't need the slave class to contain the code to hook this up, you can just as easily do this in your CreateSlaveClass method:

SlaveClass sc = new SlaveClass();
ChangeHappenedEvent += sc.ChangeHappened;
return sc;

这基本上会采用事件系统,而是让大师班code执行事件的所有接线。

This will basically use the event system, but let the MasterClass code do all the wiring of the events.

是否只要在SlaveClass对象住的单身类?如果没有,那么你需要处理时,他们变得​​陈旧的情况下/不再需要,在上述情况下(基本上是两个你和我),你持有一个参考的大师班的那些对象,因此他们永远不会进行垃圾回收,除非你强行删除这些事件或注销的接口。

Does the SlaveClass objects live as long as the singleton class? If not, then you need to handle the case when they become stale/no longer needed, as in the above case (basically in both of yours and mine), you're holding a reference to those objects in your MasterClass, and thus they will never be eligible for garbage collection, unless you forcibly remove those events or unregisters the interfaces.


要处理与SlaveClass不住只要大师班,你会遇到同样的耦合问题,因为你的评论也指出这一问题。

To handle the problem with the SlaveClass not living as long as the MasterClass, you're going to run into the same coupling problem, as you also noted in the comment.

处理(注意引号),这可能是没有真正直接链接到SlaveClass对象上正确的方法,而是创建一个包装对象,在内部将调用此方法的一种方式。从这样做的好处是,包装对象可以在内部使用WeakReference的对象,所以,一旦你的SlaveClass对象符合垃圾收集,它可能会被收集起来,然后下一次你试图调用就可以了正确的方法,你会注意到这一点,因此你必须清理。

One way to "handle" (note the quotes) this could be to not really link directly to the correct method on the SlaveClass object, but instead create a wrapper object that internally will call this method. The benefit from this would be that the wrapper object could use a WeakReference object internally, so that once your SlaveClass object is eligible for garbage collection, it might be collected, and then the next time you try to call the right method on it, you would notice this, and thus you would have to clean up.

例如,像这样(在这里我打字没有Visual Studio的智能感知和编译器的好处,请利用这个code的含义,而不是语法(错误)。)

For instance, like this (and here I'm typing without the benefit of a Visual Studio intellisense and a compiler, please take the meaning of this code, and not the syntax (errors).)

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;
    }
}

在你的大师班,你会因此做这样的事情:

In your MasterClass, you would thus do something like this:

SlaveClass sc = new SlaveClass();
WrapperClass wc = new WrapperClass(sc);
ChangeHappenedEvent += wc.ChangeHappened;
return sc;

一旦SlaveClass对象的收集,从你的大师班到事件处理程序的下一个电话(但不早于这一点)来更改通知他们,所有的包装不再有一个对象将被删除。

Once the SlaveClass object is collected, the next call (but not sooner than that) from your MasterClass to the event handlers to inform them of the change, all those wrappers that no longer has an object will be removed.

这篇关于C#::何时使用从事件处理接口衍生事件或对象的集合?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆