在基于集合的项目中传播事件

时间:2010-07-20 15:09:11

标签: .net events event-propagation

我在.NET 4中有一个基于集合的项目。我的意思是,我有一个主集合,称之为“系统”,它由帧组成,每个帧由卡组成,这些是反过来由渠道组成。因此,它看起来像System-> Frame-> Card-> Channel。所有这些都表示为对象,它们之间存在父子关系。从本质上讲,Channel只暴露给Card,Card只暴露给Frame,而Frame只暴露给System。

理想情况下,我希望仅将方法从System类公开给外部世界。但是,Channel,Card和Frame类中会发生重要事件。目前,我处理它们的方式是通过传播。假设在Channel中发生了一个事件。此事件首先在Card中引发,然后在Frame中引发,最后在System中引发。您可以看到这会导致很多代码。但我主要关心的不是代码,而是性能。

你认为这种传播会严重影响我的表现吗?有没有办法让它更有效率?我还有其他选择吗?我的收藏品相对较小。系统是1,帧< 16,卡< 256,频道< 8192.大多数数据都存储在Channel类中,该类只包含原始对象。

EDITS

以下是我在Card中为频道提出的事件所拥有的代码:

protected virtual void OnChannelPropertyChanged(Object sender, PFPropertyChangedEventArgs e)
    {
        try
        {
            EventHandler<PFPropertyChangedEventArgs> handler = ChannelPropertyChanged;
            TestEventArgs_ChannelPropertyChanged = e;
            if (handler != null)
            {
                handler(sender, e);
            }
        }
        catch (Exception ex)
        {
            Milltown.MTCore.mtException mtEx = new Milltown.MTCore.mtException((int)PFExceptions.Exception_Hidden_FuctionLevel, ex,
            PFCommonVariables.ApplicationPlatform, PFCommonVariables.ApplicationDataSource, "PFCard:OnChannelPropertyChanged");
        }
    }

当我在Card类中的卡片中添加一个频道时,我打电话给:

channel.ChannelPropertyChanged += this.OnChannelPropertyChanged;

2 个答案:

答案 0 :(得分:3)

您可以在System类中执行此操作:

event EventHandler FrameEvent
{
    add { this.frame.FrameEvent += value; }
    remove { this.frame.FrameEvent -= value; }
}

所以如果客户这样做

system.FrameEvent += Handler;

处理程序实际上附加到Frame类中的Event。

答案 1 :(得分:2)

回答是否影响您的表现的唯一方法是测试它:尝试以某种方式宣传事件,然后再尝试直接附加事件。看哪个更快。

话虽如此,我无法想象当你有一些连续的委托调用而不是一次调用时,你会发现很多 - 如果有的话 - 对性能有可测量的影响。是的,委托调用的速度比实际方法稍慢,因此,在所有条件相同的情况下,添加更多级别的间接比使用常规方法调用具有更大的影响,但这有点过早优化。

如果有人问你如何做你想做的事情,你的方法就是我的建议。除非有问题,否则请继续使用它。

修改

在回答你对另一个答案的评论时,我想扩大。 C#事件具有所谓的“属性语法”。如果在类中明确实现,它看起来像这样:

private EventHandler eventDelegate;

public event EventHandler MyEvent
{
    add { eventDelegate += value; }
    remove { eventDelegate -= value; }
}

(实际上,它使用Delegate.Combine,但这在这里并不重要)

当您附加到某个活动时,它实际上会调用add代码,并将该代理传递给value; remove也是如此。

当您使用如下的速记事件语法时:

public event EventHandler MyEvent;

它实际上生成的封面内容与我上面发布的代码非常相似。但是,如果您明确说明,则可以在addremove处理程序中执行任何操作。这意味着您可以将目标委托重定向到其他位置。在另一个答案的情况下,它将委托重定向到子对象。

当且仅当以下条件成立时,

  1. 父母与子女之间存在1:1的相关性,相关对象不会改变
  2. 可以接受对子对象的引用(object
  3. 如果你有多个孩子,那么技术上可以做到(你可以在add中循环并附加到所有这些孩子并在remove中删除所有这些孩子),但是更多难以管理。如果在附加事件后相关对象或对象集合可能发生变化,那么几乎不可能进行协调。

    此外,如果您的活动遵循建议的事件做法(将触发对象作为sender传递),那么因为您将目标直接附加到子事件而不是自己提升,那么您将通过此参数公开对子对象的引用。我不知道这是否与你相关或接受,但它应该被视为