6

我一直在寻找使用弱事件模式订阅事件。使用 .NET 4.5 框架,我们有一个看起来很漂亮的WeakEventManager类。弱订阅事件就像

WeakEventManager<EventSource, SomeEventEventArgs>.AddHandler(source, "SomeEvent", source_SomeEvent);

但是,我不是“字符串类型”代码的忠实拥护者。我一直在尝试找到一种方法来使用要订阅的事件的字符串名称。我发现获取事件名称的唯一方法是在定义事件的类中使用 lambda 表达式。在我的场景中,我拥有定义事件的类,因此我可以随意更改它。我一直在尝试找到一种干净的方式来订阅和取消订阅我的活动,这是我最不喜欢的。

public event EventHandler<EventArgs> LoggingOn;
public event EventHandler<EventArgs> LoggingOn_Weak
{
    add
    {
        var eventName = this.GetEventName(() => this.LoggingOn);
        WeakEventManager<CurrentUser, EventArgs>.AddHandler(this, eventName, value);
    }

    remove
    {
        var eventName = this.GetEventName(() => this.LoggingOn);
        WeakEventManager<CurrentUser, EventArgs>.RemoveHandler(this, eventName, value);
    }
}

// In a base class view model in my scenario
private string GetEventName<T>(System.Linq.Expressions.Expression<Func<T>> expression)
{
    return (expression.Body as System.Linq.Expressions.MemberExpression).Member.Name;
}

protected void OnLoggingOn(object sender, EventArgs e)
{
    var handler = this.LoggingOn;
    if (handler != null)
    {
        handler(sender, e);
    }
}

Using custom event accessors I was able to avoid clunky (in my opinion) methods like LoggingOn_Subscribe(EventHandler) or adding name properties for each event. Unfortunately it is not so intuitive in that people subscribing to the event are doing so in the classic manner but have no idea other than the "_Weak" part of the name that indicates it is being subscribed to weakly.

As for my questions..

1) I have never used weak events or custom event accessors before. The code above appears to work, however, I would just like to make sure there is nothing technically wrong with it. Is there anything I'm doing here to shoot myself in the foot?

2) From a design perspective, is this a terrible idea? Are there any major design concerns I should consider? Is there better alternative? Should i just suck it up and subscribe from my subscriber using a stringly-typed event name?

Thoughts?

4

2 回答 2

3

With .NET 4.6 you can now use the nameof() expression:

WeakEventManager<IMyGrid, MyEventArgs>.AddHandler(myGrid, nameof(IMyGrid.MouseDown), OnMouseDown);
于 2016-12-05T00:49:18.417 回答
-1

What you could do is use the built-in System.ComponentModel.EventHandlerList. This class is a container for all of your object's event handler delegates. The primary benefit is that no storage is allocated on your object for each event unless there is actually someone subscribed to an event.

The secondary benefit is that in order to use it, you must provide a key for your event.

class MyObject
{
    protected EventHandlerList Events = new EventHandlerList();

    public static Event1Key = new object();
    public event Event1
    {
        add { Events.AddHandler(Event1Key, value); }
        remove { Events.RemoveHandler(Event1Key, value); }
    }
}

Now you could create a variation of WeakEventManager that accepted keys rather than string names. So the consumer could say

WeakEventManager<EventSource, SomeEventEventArgs>.AddHandler(source, EventSource.Event1Key, source_SomeEvent);
于 2012-10-26T18:10:58.817 回答