非委托类型的事件

时间:2009-07-15 21:29:59

标签: c# .net events delegates

我已经实现了一个类似于这个界面的类:

[ImmutableObject(true)]
public interface ICustomEvent
{
    void Invoke(object sender, EventArgs e);

    ICustomEvent Combine(EventHandler handler);
    ICustomEvent Remove(EventHandler handler);

    ICustomEvent Combine(ICustomEvent other);
    ICustomEvent Remove(ICustomEvent other);
}

此CustomEvent类的工作方式与MulticastDelegate非常相似。它可以调用。它可以与另一个CustomEvent结合使用。并且可以从另一个CustomEvent中删除CustomEvent。

现在,我想声明一个这样的类:

class EventProvider
{
    public event CustomEvent MyEvent;

    private void OnMyEvent()
    {
        var myEvent = this.MyEvent;
        if (myEvent != null) myEvent.Invoke(this, EventArgs.Empty);
    }
}

不幸的是,这段代码没有编译。出现编译器错误CS0066:

'EventProvider.MyEvent':事件必须是委托类型

基本上,我需要的是一个具有添加删除访问者的属性,而不是获取设置 。我认为唯一的方法是使用事件关键字。我知道一个明显的替代方案是声明两个可以进行添加和删除的方法,但我也想避免这样做。

有人知道这个问题是否有一个很好的解决方案?我想知道是否有任何方法可以欺骗编译器接受非委托类型作为事件。也许是自定义属性。

顺便说一下,有人在expert-exchange.com上提出了类似的问题。由于该网站不是免费的,我看不到回复。以下是主题:http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_21697455.html

4 个答案:

答案 0 :(得分:5)

试试这个:

CustomEvent myEvent

public event EventHandler MyEvent {
    add { myEvent = myEvent.Combine(value); }
    remove {myEvent = myEvent.Remove(value); }
}

您可以添加和删除正常的EventHandler委托,它将执行addremove访问者。


编辑:您可以找到一个弱事件实施here 2 nd 编辑:或here

答案 1 :(得分:2)

如果您希望能够在事件中添加和删除CustomEvent个对象(而不是常规代理),则有两个选项:

从ICustomEvent到EventHandler(或其他一些委托)进行隐式转换,返回ICustomEvent的实例方法(可能是Invoke),然后使用委托的Target属性获取add中的原始ICustomEvent, remove访问者。

编辑:像这样:

CustomEvent myEvent;
public event EventHandler MyEvent {
    add {
        if (value == null) throw new ArgumentNullException("value");
        var customHandler = value.Target as ICustomEvent;

        if (customHandler != null)
            myEvent = myEvent.Combine(customHandler);
        else
            myEvent = myEvent.Combine(value);   //An ordinary delegate
    }
    remove {
        //Similar code
    }
}

请注意,如果第一个处理程序是委托,您仍需要弄清楚如何添加第一个处理程序(如果myEvent字段为null


创建一个CustomEvent类型的可写属性,然后重载+-运算符以允许属性上的+=-=

编辑:为了防止您的调用者覆盖事件,您可以在CustomEvent中公开先前的值(我假设它的工作方式类似于immutable stack),并且在setter中,添加

if (myEvent.Previous != value && value.Previous != myEvent)
    throw new ArgumentException("You cannot reset a CustomEvent", "value");

请注意,删除最后一个处理程序后,valuemyEvent.Previous都将为null

答案 2 :(得分:1)

您想要完成哪些不能使用委托/事件?

这尖叫Reinventing the Square Wheel (bottom of the page),但我也不能理解这个问题。

答案 3 :(得分:0)

为什么不尝试在CustomEvent类上使用“+ =”和“ - =”运算符? 您不能直接覆盖“+ =”和“ - =”运算符,但它们由“+”和“ - ”运算符计算。

分配运算符不能重载,但是+ =,例如,使用+进行评估,可以重载。

http://msdn.microsoft.com/en-us/library/8edha89s(VS.90).aspx

因此,您可以拥有一个可以由+ =和 - =运算符组合的字段或属性,而不是使用类似事件的添加和删除方法。此外,它将组合逻辑封装在您自己的CustomEvent类中。

Carlos Loth。