Создание пользовательских событий - Объектный Отправитель или Введенный Отправитель?

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

Скажите, что я создаю пользовательский класс под названием Подписка, и она реализует ISubscription, и у меня есть некоторое событие args названный SubscriptionEventArgs. Если Подписка имела событие под названием Измененный что не так об Измененной подписи события (отправитель ISubscription, SubscriptionEventArgs e)?

Немного кода, чтобы помочь управлять вопросом:

public class SubscriptionEventArgs : EventArgs
{
    // guts of event args go here
}

public interface ISubscription
{
    event Action<ISubscription, SubscriptionEventArgs> Changed;
}

public class Subscription : ISubscription
{
    public event Action<ISubscription, SubscriptionEventArgs> Changed;

    private void OnChanged(SubscriptionEventArgs e)
    {
        if (Changed!= null)
        {
            Changed(this, e);
        }
    }
}

Если Вы просто презираете использование действия вместо "EventHandler" затем, Вы могли бы сделать то же самое, но с пользовательским универсальным "EventHandler".

public delegate void EventHandler<TSender, TEventArgs>(TSender sender, TEventArgs e);

public class SubscriptionEventArgs : EventArgs
{
    // guts of event args go here
}

public interface ISubscription
{
    event EventHandler<ISubscription, SubscriptionEventArgs> Changed;
}

public class Subscription : ISubscription
{
    public event EventHandler<ISubscription, SubscriptionEventArgs> Changed;

    private void OnChanged(SubscriptionEventArgs e)
    {
        if (Changed!= null)
        {
            Changed(this, e);
        }
    }
}

В ответ на запрос ханьцев на демонстрационный обработчик событий:

public class SubscriptionCollection
{
    // what is actually holding the subscriptions is not really relevant to the question
    private List<ISubscription> _subscriptions;

    public SubscriptionCollection()
    {
        _subscriptions = new List<ISubscription>();
    }

    public void Add(ISubscription subscription)
    {
        subscription.Changed += new EventHandler<ISubscription, SubscriptionEventArgs>(Subscription_Changed);
        _subscriptions.Add(subscription);
    }

    private void Subscription_Changed(ISubscription sender, SubscriptionEventArgs e)
    {
        // Now when the subscription changed event is being handled by the collection
        // I don't have to look up the subscription in the list by some key and I don't 
        // have to cast sender to the correct type because the event handler was typed
        // correctly from the beginning.
    }
}

Поиск подписки в списке мог бы казаться тривиальным, но что, если я работаю с очень большими наборами данных и новыми объемами данных, прибывают в приложение через поток в реальном времени. Стоимость необходимости остановиться и вытащить ссылку из списка или пройти шаги кастинга не имеет смысла. Они дали нам дженерики в 2,0 для решения той проблемы, таким образом, я не понимаю, почему мы не получили универсальный обработчик событий также, и это привело меня к вопросу что не так с универсальным обработчиком событий?

8
задан Ryan Pedersen 15 July 2010 в 04:00
поделиться

1 ответ

Я совершенно не понимаю, почему при разработке .Net Framework v2 MS не предоставила EventHandler именно так, как вы описали - с TSender и TEventArgs как общие аргументы. (В v1 и v1.1, поскольку у них не было дженериков, я полностью понимаю, почему они не сделали тысячи дополнительных типов делегатов для обработки всех возможных событий.) Если я правильно помню, вы все равно можете использовать обобщенный обработчик чтобы прослушать более конкретное событие:

public event EventHandler<Button, MouseDownEventArgs> MouseDown;

private void ObservingMethod(object sender, EventArgs e) { }

MouseDown += new EventHandler<Button, MouseDownEventArgs>(ObservingMethod);

Поскольку вы не подвергаете наблюдателя наблюдаемому, я не понимаю, как это может быть проблемой; вы просто предотвращаете необходимость проверки типов «на всякий случай», как только дойдете до обработчика событий. Я думаю, что это была бы фантастическая практика, хотя и немного нестандартная, поскольку MS решила не включать ее.

Как отмечалось в моем комментарии выше, я бы предпочел увидеть следующее определение EventHandler, чтобы вы действительно всегда могли использовать очень обобщенный метод обработчика в качестве моего примера кода:

public delegate void EventHandler<TSender, TEventArgs>(TSender sender, TEventArgs e)
    where TEventArgs : EventArgs;
0
ответ дан 6 December 2019 в 04:33
поделиться
Другие вопросы по тегам:

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