非委托类型的事件类型、事件

2023-09-03 02:09:56 作者:臨時男友

我已经实现了一个类,它看起来像这样的界面:

I've implemented a class that looks like this interface:

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

这个自定义事件类的工作方式很像一个MulticastDelegate。它可以调用。它可与另一CustomEvent的组合。和一个自定义事件可以从另一CustomEvent的除去。

This CustomEvent class works much like a MulticastDelegate. It can invoked. It can be combined with another CustomEvent. And a CustomEvent can be removed from another CustomEvent.

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

Now, I want to declare a class like this:

class EventProvider
{
    public event CustomEvent MyEvent;

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

不幸的是,这个code不能编译。出现一个编译器错误CS0066:

Unfortunately, this code does not compile. A Compiler Error CS0066 appears:

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

基本上,我需要的是有添加和删除访问,而不是获取和设置属性。我认为有,唯一的方法是使用在活动关键字。我知道,一个明显的替代方案是声明了两个方法,会做的添加和删除,但我想,以避免这一点。

Basically, what I need is a property that has add and remove accessors instead of get and set. I think the only way to have that is using the event keyword. I know that one obvious alternative is to declare two methods that would do the adding and removing, but I want to avoid that too.

有谁知道如果有一个很好的解决方案这个问题呢?我不知道是否有什么办法可以欺骗编译器接受非委托类型的事件。自定义属性,也许吧。

Does anybody knows if there is a nice solution this problem? I wonder if there is any way to cheat the compiler to accept a non-delegate type as an event. A custom attribute, perhaps.

顺便说一句,有人问在experts-exchange.com过类似的问题。由于该网站是不是免费的,我看不到回应。下面是主题: http://www.experts-exchange.com/编程/语言/ C_Sharp / Q_21697455.html

By the way, someone asked a similar question in experts-exchange.com. Since that site is not free, I can't see the responses. Here is the topic: http://www.experts-exchange.com/Programming/Languages/C_Sharp/Q_21697455.html

推荐答案

如果您希望能够添加和删除自定义事件从事件对象(而不是常规代表),有两个选择:

If you want to be able to add and remove CustomEvent objects from the event (instead of regular delegates), there are two options:

请隐式转换从ICustomEvent到事件处理程序(或其他代表),返回ICustomEvent(可能调用)的实例方法,然后使用该委托的目标属性来获得原始ICustomEvent在添加删除访问。

Make an implicit cast from ICustomEvent to EventHandler (or some other delegate) that returns an instance method of ICustomEvent (probably Invoke), then use the Target property of the delegate to get the original ICustomEvent in the add and remove accessors.

修改:像这样的:

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 字段是

Note that you'll still need to figure out how to add the first handler if it's a delegate (if the myEvent field is null)

请键入自定义事件的可写性,然后重载 + - 运营商允许 + = - 。= 的属性

Make a writable property of type CustomEvent, then overload the + and - operators to allow += and -= on the property.

修改:为prevent被覆盖的情况下您的来电,您可以在暴露的自定义事件previous值(我假设它就像一个不可改变的堆栈),并在二传,添加

EDIT: To prevent your callers from overwriting the event, you could expose the previous value in CustomEvent (I'm assuming it works like an immutable stack) and, in the setter, add

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

请注意,当最后一个处理器被拆除,既 myEvent。previous

Note that when the last handler is removed, both value and myEvent.Previous will be null.