Слабая модель обработчика событий для использования с лямбдами

Обновить : более новые версии должны использовать пакет php-sqlite3 вместо php5-sqlite. Поэтому используйте это, если вы используете последнюю версию ubuntu:

sudo apt-get install sqlite php-sqlite3

Оригинальный ответ на вопрос:

sudo apt-get install sqlite php5-sqlite
sudo /etc/init.d/apache2 restart

Если ваш phpinfo () не показывает pdo_sqlite line (в моем случае, на моем сервере Ubuntu), вам просто нужно запустить строки выше, и тогда вам будет хорошо идти.

37
задан Community 23 May 2017 в 11:53
поделиться

2 ответа

Вот общий алгоритм (отредактирован для повышения эффективности) что я избавился от сонливости - и я также исправил ошибку, о которой никто не сообщил) ...:)

Это займет вечность (не говоря уже о большом количестве памяти), если я буду сравнивать содержимое каждого файла против друг друга. Вместо этого, почему бы нам сначала не применить тот же поиск к их размерам, а затем сравнить контрольные суммы для этих файлов одинакового размера.

Итак, когда мы md5суммируем каждый файл (см. Digest :: MD5 ) вычислить их размеры, мы можем использовать хеш-таблицу для сопоставления за нас, сохраняя совпадения вместе в arrayrefs:

//This overload handles any type of EventHandler
public static void SetAnyHandler<S, TDelegate, TArgs>(
    Func<EventHandler<TArgs>, TDelegate> converter, 
    Action<TDelegate> add, Action<TDelegate> remove,
    S subscriber, Action<S, TArgs> action)
    where TArgs : EventArgs
    where TDelegate : class
    where S : class
{
    var subs_weak_ref = new WeakReference(subscriber);
    TDelegate handler = null;
    handler = converter(new EventHandler<TArgs>(
        (s, e) =>
        {
            var subs_strong_ref = subs_weak_ref.Target as S;
            if(subs_strong_ref != null)
            {
                action(subs_strong_ref, e);
            }
            else
            {
                remove(handler);
                handler = null;
            }
        }));
    add(handler);
}

// this overload is simplified for generic EventHandlers
public static void SetAnyHandler<S, TArgs>(
    Action<EventHandler<TArgs>> add, Action<EventHandler<TArgs>> remove,
    S subscriber, Action<S, TArgs> action)
    where TArgs : EventArgs
    where S : class
{
    SetAnyHandler<S, EventHandler<TArgs>, TArgs>(
        h => h, add, remove, subscriber, action);
}

Деталь

Моей отправной точкой был отличный ответ Егора (см. Ссылку на версию с комментариями):

public static void Link(Publisher publisher, Control subscriber) {
    var subscriber_weak_ref = new WeakReference(subscriber);
    EventHandler<ValueEventArgs<bool>> handler = null;
    handler = delegate(object sender, ValueEventArgs<bool> e) {
            var subscriber_strong_ref = subscriber_weak_ref.Target as Control;
            if (subscriber_strong_ref != null) subscriber_strong_ref.Enabled = e.Value;
            else {
                    ((Publisher)sender).EnabledChanged -= handler;
                    handler = null; 
            }
    };

    publisher.EnabledChanged += handler;
}

Что меня беспокоило, так это то, что событие жестко закодировано в методе. Таким образом, это означает, что для каждого нового события существует новый метод записи.

Я повозился и сумел придумать это общее решение:

private static void SetAnyGenericHandler<S, T>(
     Action<EventHandler<T>> add,     //to add event listener to publisher
     Action<EventHandler<T>> remove,  //to remove event listener from publisher
     S subscriber,                    //ref to subscriber (to pass to action)
     Action<S, T> action)             //called when event is raised
    where T : EventArgs
    where S : class
{
    var subscriber_weak_ref = new WeakReference(subscriber);
    EventHandler<T> handler = null;
    handler = delegate(object sender, T e)
    {
        var subscriber_strong_ref = subscriber_weak_ref.Target as S;
        if(subscriber_strong_ref != null)
        {
            Console.WriteLine("New event received by subscriber");
            action(subscriber_strong_ref, e);
        }
        else
        {
            remove(handler);
            handler = null;
        }
    };
    add(handler);
}

Однако проблема с этим решением в том, что оно ТОЛЬКО общее, оно может не обрабатывает стандартные winforms MouseUp, MouseDown и т. д.

Поэтому я попытался сделать его даже более универсальным:

private static void SetAnyHandler<T, R>(
    Action<T> add,      //to add event listener to publisher
    Action<T> remove,   //to remove event listener from publisher
    Subscriber subscriber,  //ref to subscriber (to pass to action)
    Action<Subscriber, R> action) 
    where T : class
{
    var subscriber_weak_ref = new WeakReference(subscriber);
    T handler = null;
    handler = delegate(object sender, R e) //<-compiler doesn't like this line
    {
        var subscriber_strong_ref = subscriber_weak_ref.Target as Subscriber;
        if(subscriber_strong_ref != null)
        {
            action(subscriber_strong_ref, e);
        }
        else
        {
            remove(handler);
            handler = null;
        }
    };
    remove(handler);
}

Однако, как я намекнул здесь , это не компилируется, потому что нет способа ограничить T как делегата.

В этот момент я в значительной степени сдался. Нет смысла бороться со спецификациями C #.

Однако вчера я обнаружил Observable. FromEvent из фреймворка Reactive у меня не было реализации, но его использование показалось немного знакомым и очень интересным:

var mousedown = Observable.FromEvent<MouseEventHandler, MouseDownEventArgs>(
      h => new MouseEventHandler(h),
      h => control.MouseDown += h,
      h => control.MouseDown -= h);

Это был первый аргумент, который привлек мое внимание. Это обходной путь при отсутствии ограничения типа делегата. Мы берем это, передавая функцию, которая создаст делегата.

Объединение всего этого дает нам решение, показанное в верхней части этого ответа.

Запоздалые мысли

Я настоятельно рекомендую найти время, чтобы узнать о реактивный фреймворк (или как он там называется). Это ОЧЕНЬ интересно и немного умопомрачительно. Я подозреваю, что это также сделает такие вопросы полностью излишними.

Пока что самым интересным, что я видел, были видео на Channel9 .

У меня есть реализация, но использование показалось немного знакомым и очень интересным:

var mousedown = Observable.FromEvent<MouseEventHandler, MouseDownEventArgs>(
      h => new MouseEventHandler(h),
      h => control.MouseDown += h,
      h => control.MouseDown -= h);

Это был первый аргумент, который привлек мое внимание. Это обходной путь при отсутствии ограничения типа делегата. Мы берем это, передавая функцию, которая создаст делегата.

Объединение всего этого дает нам решение, показанное в верхней части этого ответа.

Запоздалое размышление

Я настоятельно рекомендую найти время, чтобы узнать о реактивный фреймворк (или как он там называется). Это ОЧЕНЬ интересно и немного умопомрачительно. Я подозреваю, что это также сделает такие вопросы полностью излишними.

Пока что самым интересным, что я видел, были видео на Channel9 .

У меня есть реализация, но использование показалось немного знакомым и очень интересным:

var mousedown = Observable.FromEvent<MouseEventHandler, MouseDownEventArgs>(
      h => new MouseEventHandler(h),
      h => control.MouseDown += h,
      h => control.MouseDown -= h);

Это был первый аргумент, который привлек мое внимание. Это обходной путь при отсутствии ограничения типа делегата. Мы берем это, передавая функцию, которая создаст делегата.

Объединение всего этого дает нам решение, показанное в верхней части этого ответа.

Запоздалые мысли

Я настоятельно рекомендую найти время, чтобы узнать о реактивный фреймворк (или как он там называется). Это ОЧЕНЬ интересно и немного умопомрачительно. Я подозреваю, что это также сделает такие вопросы полностью излишними.

Пока что самым интересным, что я видел, были видео на Channel9 .

var mousedown = Observable.FromEvent<MouseEventHandler, MouseDownEventArgs>(
      h => new MouseEventHandler(h),
      h => control.MouseDown += h,
      h => control.MouseDown -= h);

Это был первый аргумент, который привлек мое внимание. Это обходной путь при отсутствии ограничения типа делегата. Мы берем это, передавая функцию, которая создаст делегата.

Объединение всего этого дает нам решение, показанное в верхней части этого ответа.

Запоздалые мысли

Я настоятельно рекомендую найти время, чтобы узнать о реактивный фреймворк (или как он там называется). Это ОЧЕНЬ интересно и немного умопомрачительно. Я подозреваю, что это также сделает такие вопросы полностью излишними.

Пока что самым интересным, что я видел, были видео на Channel9 .

var mousedown = Observable.FromEvent<MouseEventHandler, MouseDownEventArgs>(
      h => new MouseEventHandler(h),
      h => control.MouseDown += h,
      h => control.MouseDown -= h);

Это был первый аргумент, который привлек мое внимание. Это обходной путь при отсутствии ограничения типа делегата. Мы берем это, передавая функцию, которая создаст делегата.

Объединение всего этого дает нам решение, показанное в верхней части этого ответа.

Запоздалое размышление

Я настоятельно рекомендую найти время, чтобы узнать о реактивный фреймворк (или как он там называется). Это ОЧЕНЬ интересно и немного умопомрачительно. Я подозреваю, что это также сделает такие вопросы полностью излишними.

Пока что самым интересным, что я видел, были видео на Channel9 .

Собирая все это вместе, мы получаем решение, показанное в верхней части этого ответа.

Запоздалое размышление

Я настоятельно рекомендовал потратить время на изучение реактивного фреймворка (или того, как он в итоге называется). Это ОЧЕНЬ интересно и немного умопомрачительно. Я подозреваю, что это также сделает такие вопросы полностью излишними.

Пока что самым интересным, что я видел, были видео на Channel9 .

Собирая все это вместе, мы получаем решение, показанное в верхней части этого ответа.

Запоздалое размышление

Я настоятельно рекомендовал потратить время на изучение реактивного фреймворка (или того, как он в итоге называется). Это ОЧЕНЬ интересно и немного умопомрачительно. Я подозреваю, что это также сделает такие вопросы полностью излишними.

Пока что самым интересным, что я видел, были видео на Channel9 .

34
ответ дан 27 November 2019 в 03:51
поделиться

Подход Дастина Кэмпбелла уже превосходен. Единственное, что осталось, кроме интегрированного в .NET решения, это действительно простой способ создания действительно общих слабых обработчиков событий:

http://puremsil.wordpress.com/2010/05/03/generic-weak-event-handlers/

2
ответ дан 27 November 2019 в 03:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: