Использование WeakEventManager со статическим событием - PullRequest
8 голосов
/ 16 января 2012

Можно ли создать слабый приемник событий для статического события с помощью WeakEventManager?

Я хотел бы создать слабый прослушиватель событий для статического события CompositionTarget.Rendering, чтобы избежать утечек памяти, когда я не знаю время жизни исходного элемента WPF / Silverlight.

Я реализовал менеджер событий рендеринга с помощью шаблона слабого события :

public class RenderingEventManager : WeakEventManager
{
    public static void AddListener(IWeakEventListener listener)
    {
        CurrentManager.ProtectedAddListener(null, listener);
    }

    public static void RemoveListener(IWeakEventListener listener)
    {
        CurrentManager.ProtectedRemoveListener(null, listener);
    }

    private static RenderingEventManager CurrentManager
    {
        get
        {
            var managerType = typeof(RenderingEventManager);
            var manager = (RenderingEventManager)GetCurrentManager(managerType);
            if (manager == null)
            {
                manager = new RenderingEventManager();
                SetCurrentManager(managerType, manager);
            }
            return manager;
        }
    }

    protected sealed override void StartListening(object source)
    {
        CompositionTarget.Rendering += this.OnCompositionTargetRendering;
    }

    protected sealed override void StopListening(object source)
    {
        CompositionTarget.Rendering -= this.OnCompositionTargetRendering;
    }

    void OnCompositionTargetRendering(object sender, EventArgs e)
    {
        this.DeliverEvent(sender, e);
    }
}

и протестировал менеджер в простом окне:

public partial class Window1 : Window, IWeakEventListener
{
    public Window1()
    {
        InitializeComponent();
        RenderingEventManager.AddListener(this);
    }

    bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
    {
        return true;
    }
}

Метод ReceiveWeakEvent не вызывается. OnCompositionTargetRendering вызывается, но похоже, что DeliverEvent работает не так, как я ожидал. Добавление слушателей к событиям экземпляра, таким как Button.Click, работает нормально ... Тестовый проект находится на клиентском профиле .NET 4.0.

В сообщении о Microsoft Connect от 2009 года говорится, что статические события не поддерживаются, но я проверил исходный код WeakEventManager, и он выглядит нормально:

    protected void ProtectedAddListener(object source, IWeakEventListener listener) 
    { 
        Debug.Assert(listener != null, "Listener cannot be null");

        object sourceKey = (source != null) ? source : StaticSource;
        ...
    }

1 Ответ

8 голосов
/ 18 января 2012

Сам понял: измените аргумент sender метода DeliverEvent на null:

void OnCompositionTargetRendering(object sender, EventArgs e)
{
    this.DeliverEvent(null, e);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...