4

这些天来,我几乎只在我的 C# WPF 应用程序中使用 Reactive Extensions。添加和删​​除事件处理程序是一种反模式,我完全嫉妒 F# 事件实现 IObservable 的事实。

为了帮助 C# 开发人员,RX 人员提供了以下方法(以及其他一些不同类型的安全性)

public static 
IObservable<EventPattern<TEventArgs>> 
FromEventPattern<TDelegate, TEventArgs>
    ( Action<TDelegate> addHandler
    , Action<TDelegate> removeHandler
)
where TEventArgs : EventArgs

http://msdn.microsoft.com/en-us/library/hh211731(v=vs.103).aspx

我会这样使用它

var movingEvents = Observable.FromEventPattern<MouseEventHandler, 
    MouseEventArgs>(h => this.MouseMove += h, h => this.MouseMove -= h);

然而,这很乏味。我想做的是

var movingEvents = h.MouseMoveObserver();

并完成它。这种扩展方法看起来像

IObservable<MouseEventArgs> MouseMoveObserver(this Canvas This){
    return Observable.FromEventPattern<MouseEventHandler, 
    MouseEventArgs>(h => This.MouseMove += h, h => This.MouseMove -= h); 
}

这不是火箭科学,我一直在考虑建立一个库,在我需要时一次添加这些扩展方法。但是我确信一些智能 cookie 可以编写一个 T4 模板,通过反射处理 WPF 库中的所有控件并生成我需要的所有扩展方法。我的问题是...

有没有人写过这样的代码生成器来将事件映射到上面的可观察对象,如果没有,有人会对如何做到这一点有任何建议吗?我对 .Net 反射不是很好,但一些种子代码可能会让我开始。

4

1 回答 1

6

要获取从 FrameworkElement 派生的所有类型,您可以使用

var typesToDo = from t in Assembly.GetAssembly(typeof(FrameworkElement)).GetTypes()
                where t.IsSubclassOf(typeof(FrameworkElement)) 
                        && t.IsPublic 
                        && t.GetEvents().Any()
                select t;

然后您可以使用type.GetEvents()来获取每种类型的事件。您返回的 EventInfo 将让您查看名称、类型、参数等内容。

您需要做一些额外的工作来应对通用事件,但这并不是一个巨大的数量。

在 GitHub 上放了一个示例程序以及一个输出示例

存在某些输出无法正常工作的风险,我还没有全部尝试过 :) 我确实确保它们都可以构建,并且至少其中一些可以正常工作。

于 2013-02-16T14:58:51.117 回答