2011-08-16 30 views
2

我把“事件”放在引号中,因为我意识到这是一种语法糖,而不是真正的类型。有没有办法完成等同于通过引用传递“事件”?

我有一些事件被简单地链接到另一个类中的匹配事件。因此,当事件引发,该通道就像是

雷塞 - >代理 - >用户

所以在Proxy类我有这样一个共同的模式:

Raiser.SomeEvent += 
    (_, args) => 
    { 
     if (this.SomeEvent != null) 
      this.SomeEvent(this, args); 
    }; 

收拾我代码我想提出这个出去,返回一个新的委托包装了上述事件调用代码的另一种方法:

public static EventHandler GetHandlerDelegate(EventHandler handler, Object sender) 
{ 
    return 
     (_, args) => 
     {     
      if (handler != null) 
       handler(sender, args); 
     }; 
    }  

然后在代理我可以这样做:

Raiser.SomeEvent += GetHandlerDelegate(this.SomeEvent, this); 

哪个更合适。

那么这是好的,只要订阅者不决定订阅Proxy.SomeEvent 之后上面的调用。不幸的是,我没有像我希望的那样通过引用来传递“事件”。我现在明白了,我只是传递了调用列表,所以当OtherClass.SomeEvent发生并且调用匿名方法并调用它的“事件”(委托)时,只有当时已添加到该事件的代理我打电话给GetHandlerDelegate()。虽然这实际上足以满足我目前的情况,但以这种方式进行编码是不可接受的。

我读过一些其他的SO问题,我收集了一些名为Reactive Extensions的内容可能会有所帮助,但此时我正在寻找一个更简单的解决方案(如果有的话)。 (如果没有,我只是不会这样做。)

有没有另一种方法可以完成我想要做的事情,没有缺点?


如果这个问题不清楚,请参阅my answer,希望有助于澄清它。

回答

0

因为我原来做的目标:

Raiser.SomeEvent += GetHandlerDelegate(this.SomeEvent, this); 

是不可能的,我已经妥协,并拿出这样的:

Raiser.SomeEvent += (_, args) => RaiseEvent(this.SomeEvent, this, args); 

GetHandlerDelegate()将返回其引发事件的委托,RaiseEvent()只是(你猜对了)引发了这个事件。

public static void RaiseEvent(EventHandler _event, Object sender, EventArgs args) 
{ 
    if (_event != null) 
     _event(sender, args); 
} 

并支持活动使用自定义的EventArgs:

public static void RaiseEvent<TArgs>(EventHandler<TArgs> _event, Object sender, TArgs args) 
    where TArgs : EventArgs 
{ 
    if (_event != null) 
     _event(sender, args); 
} 

我已经投入了静态辅助类的这些方法,所以实际通话稍微难看;这里有一个例子:

ViewControl.OpenFilesetClick += (_, args) => EventHelper.Raise(OpenFilesetClick, this, args); 

(我也改名的方法来提高(),并从事件名称被传递下降可选this)。

但我不完全相信,如果这是值得考虑的替代方案可以说是更容易阅读:

ViewControl.OpenFilesetClick += (_, args) => 
{ 
    if (OpenFilesetClick != null) 
     OpenFilesetClick(this, args); 
}; 

无论如何,这是为了更多地了解事件和委托是如何工作的一个有趣的方式(或他们如何不工作)。

3

编辑:好的,我想我现在明白了。其实很简单。您应该能够编写代理只是一个事件,然后让代理自己订阅雷塞的情况下,像这样(只是EventHandler - 我就要谈这一点以后):

Proxy proxy = new Proxy(); 
raiser.SomeEvent += Proxy.Handler; 

// Then in the subscriber... 
proxy.ProxiedEvent += (whatever) 

// And the proxy class... 
public class Proxy 
{ 
    public event EventHandler ProxiedEvent; 

    public void Handler(object sender, EventArgs e) 
    { 
     EventHandler proxied = ProxiedEvent; 
     if (proxied != null) 
     { 
      // Or pass on the original sender if you want to 
      proxied(this, e); 
     } 
    } 
} 

现在,这里的困难在于使其一般工作。我目前无法想到这样做,尽管我现在有点分心。

这是你想到的那种东西,还是它至少可以帮助你以不同的方式思考事物?

+0

乔恩,谢谢你的回答,但作为一个纯粹的子Skeet凡人,我无法看到隐含的细节。换句话说,我迷路了。你能详细说明一下吗?这怎么能适用于我的问题? –

+0

@Charles:这可能是我误解了这个问题......我现在发现有点难以遵循,但这很可能是我自己的错。然而,这里的EventWrapper基本上是一种抽象“可以订阅和取消订阅的东西”的概念。从根本上说,这是一个事件。你不能将事件本身作为委托,因为它不是代表。 –

+0

我似乎有不良表达我的问题的历史,所以我敢肯定,我应该责怪任何混乱,而不是你!基本上,我想将任何委托_dA_传递给一个方法,并返回一个调用_dA_的新委托_dB_,其中,如果_dA_的调用列表发生更改,我希望在调用_dB_时调用_updated_调用列表。 (我根本没有使用过一个事件 - 只是一个代表 - 为了证实这个问题真的是关于_delegates_的工作方式)。 –

相关问题