使用匿名代理进行事件处理

为了记录:我在这里发现了一个类似的问题,但我必须详细阐述这个问题。

我的具体情况是这样的:

在Silverlight 4中, myFrameworkElement.FindName("otherElementName")方法现在似乎正常工作,但我遇到了一个问题。 当元素尚未添加到可见树时,它仍然返回null

但是现在我需要在自定义UserControl处理程序的DependencyPropertyPropertyChangedCallback中使用此功能。 在这个范围内,用户控件是否被添加到可视化树还不确定。 但是我必须对树中的另一个元素执行某种操作。 当元素已经可用时,它可以并且应该立即完成。 如果不是,它必须在可用时立即完成。 所以我想出了这样的扩展方法,我可以这样调用:

myFrameworkElement.FindNameEnsured("otherElementName",
    result => this.DoSomethingWith(result));

扩展方法的代码如下所示:

    static public void FindNameEnsured(this FrameworkElement self,
            string name, Action<object> resultAction)
    {
        if (self != null && resultAction != null)
        {
            object result = self.FindName(name);

            if (result != null)
            {
                resultAction(result);
            }
            else
            {
                RoutedEventHandler handler = null;
                handler = (sender, e) =>
                     {
                         result = self.FindName(name);
                         resultAction(result);

                         self.Loaded -= handler;
                     };

                self.Loaded += handler;
            }
        }

正如你所看到的,我必须使用一个匿名委托,因为我需要resultAction内的nameresultAction的值。 然后我退订处理程序内部的事件,因为我是一个聪明干净的人,不想泄漏。 我也不想用一些花哨的WeakEventFactories或类似的东西来打破轮子上的苍蝇。

现在这个工作顺利到目前为止。 但我有一些问题。

  • 这通常是一个足够干净的方法来取消订阅处理程序内的事件处理程序? 还是最终会杀死一只无辜的小狗?
  • 由于在匿名委托中使用外部作用域变量,是否会出现一些泄漏问题?
  • 是否有线程同步问题会导致我“错过” Loaded事件? 在这种特殊情况下,只有Silverlight的UI调度程序线程应该参与其中。 但是,如果这是一个问题,并且/或者如果我在非UI相关场景中需要类似的功能,那么f1x0r的最佳方法是什么?
  • 感谢您的耐心和时间阅读我冗长的阐述。 ;-)


  • 这应该没问题,虽然这有点痛苦。 LINQ to Rx有一个更好的取消订阅的想法 - 当你订阅时,你会得到一个IDisposable ,它会在你处置时取消订阅。 尽管如此,这并不适合现有的事件模型。
  • 我认为在这种特殊情况下你不会有任何泄漏 - 有一些边缘条件,其中使用同一范围内的变量的两个不同的匿名函数最终可以捕获它们不需要的变量,但它确实是一个边缘案件。
  • 您必须提供有关假设情况的更准确细节 - 您确切担心的是,事件如何实施等。
  • 链接地址: http://www.djcxy.com/p/51427.html

    上一篇: Event handling with an anonymous delegate

    下一篇: Func delegate with no return type