具有事件名称lambda表达式和自定义事件访问器的WeakEventManager

时间:2012-10-26 14:28:09

标签: c# .net weak-events

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

一样简单
WeakEventManager<EventSource, SomeEventEventArgs>.AddHandler(source, "SomeEvent", source_SomeEvent);

然而,我并不是'字符串型'代码的忠实粉丝。我一直试图找到一种方法来使用事件的字符串名称来订阅。我发现获取事件名称的only way是在定义事件的类中使用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);
    }
}

使用custom event accessors我能够避免使用像LoggingOn_Subscribe(EventHandler)那样笨重(在我看来)的方法,或者为每个事件添加名称属性。不幸的是,订阅该活动的人不是那么直观,而是以经典的方式这样做,但除了名称中的“_Weak”部分之外没有任何想法,这表明它正在被微弱地订阅。

至于我的问题..

1)之前从未使用过弱事件或自定义事件访问器。上面的代码似乎有效,但是,我想确保它在技术上没有任何错误。有什么我在这里做自己的脚射击吗?

2)从设计角度来看,这是一个可怕的想法吗?我应该考虑哪些主要的设计问题?还有更好的选择吗?我应该使用字符串类型的事件名称来吸收它并订阅我的订阅者吗?

思想?

2 个答案:

答案 0 :(得分:2)

使用.NET 4.6,您现在可以使用nameof()表达式:

WeakEventManager<IMyGrid, MyEventArgs>.AddHandler(myGrid, nameof(IMyGrid.MouseDown), OnMouseDown);

答案 1 :(得分:-1)

您可以使用内置的System.ComponentModel.EventHandlerList。此类是所有对象的事件处理程序委托的容器。主要好处是除非实际有人订阅了某个事件,否则不会为每个事件分配对象的存储空间。

第二个好处是,为了使用它,您必须为您的活动提供密钥。

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

现在,您可以创建WeakEventManager的变体,它接受键而不是字符串名称。所以消费者可以说

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