Объясните события ASP.NET - PullRequest
       23

Объясните события ASP.NET

1 голос
/ 25 августа 2009

Смотрите также:

понимание событий и обработчиков событий в C #

Как веб-разработчик, мне обычно не нужно создавать собственные события для объектов, поскольку большинство из них присуще странице. Тем не менее, теперь я нахожусь в довольно сложном (веб) проекте, где я думаю, что, возможно, мне придется их использовать. Я только что прочитал главу из Pro VB 2008 и платформы .NET 3.5 о событиях, делегатах и ​​лямбдах (глава 11), и хотя у меня есть лучшее представление о том, что происходит, у меня все еще есть проблемы обернуть мой разум вокруг , когда точно, чтобы использовать их и как , чтобы использовать их. Я понимаю их реализацию, но пример в книге немного надуманный.

Я надеялся, что кто-то, обладающий немного большим пониманием предмета событий, сможет дать мне действительно веский пример.

Для моего реального приложения я пытаюсь использовать событие, которое сообщит мне, когда элемент (некоторый класс с именем OrderItem) был обновлен, и выполнит действия в зависимости от того, был ли он обновлен. Я подумал об использовании свойства flag / boolean, но знаю, что это не пахнет правильно, и давно пора узнать, как правильно использовать события.

Большое спасибо!

РЕДАКТИРОВАТЬ Хорошо, я думаю, чтобы уточнить немного, какой смысл вызывать событие, когда все, что он делает, вызывает метод? Почему бы просто не вызвать метод? Это тоже не дубликат, так как я говорю концептуально, и она хочет знать конкретно об обработчиках. Кроме того, я хочу знать, в чем разница между использованием события или свойства "flag". А что люди подразумевают под «подпиской» на событие?

Ответы [ 2 ]

4 голосов
/ 25 августа 2009

Допустим, у вас есть система лифта, а часть, которая движется вверх и вниз, называется ElevatorCar. Когда человек нажимает кнопку, чтобы перейти на 5-й этаж, для ElevatorController имеет смысл вызвать метод ElevatorCar.RequestToFloor (5). Теперь, когда автомобиль действительно прибывает на 5-й этаж, имеет смысл вызвать событие наподобие ArrivedAtFloor, передав 5 в качестве аргумента. Класс ElevatorController будет подписываться на событие ArrivedAtFloor класса ElevatorCar.

Это все потому, что класс ElevatorCar «ничего не знает» о классе ElevatorController, а класс ElevatorController знает о классе ElevatorCar. Поэтому класс ElevatorCar получает инструкции с помощью методов и уведомляет внешний мир о том, что происходит с помощью событий.

Имеет ли это какой-то смысл?

EDIT:

Хорошо, во-первых, прочитайте отличный ответ, указанный в ссылке См. Также (предположим, вы это сделали). Событие - это, по сути, объект, говорящий «если вы хотите, чтобы я звонил вам всякий раз, когда происходит X, зарегистрируйте ваш метод здесь ». Регистрация обработчика события с помощью события «подписка». Это позволяет инкапсуляцию. Например, вы можете написать свой класс ElevatorCar один раз и использовать его много раз во многих других классах.

Что касается разницы между использованием события или просто вызовом метода, вы должны спросить себя, должен ли ElevatorCar знать о классе ElevatorController. Если ElevatorController вызывает ElevatorCar.GoToFloor (x), как класс ElevatorCar может «перезвонить» ElevatorController без сохранения ссылки на ElevatorController? Это означает, что вызов должен стать ElevatorCar.GoToFloor (int floor, ElevatorController ctrlr). Затем класс ElevatorCar в конечном итоге должен вызвать ctrlr.ArrivedAtFloor (floor). Но вы сталкиваетесь со множеством сложностей ... что если есть более одной машины? Вы, вероятно, должны вызвать ctrlr.ArrivedAtFloor (floor, this). Передача ссылок на себя не оптимальна.

Что касается простой установки свойства, как другой класс узнает, что он пришел и прочитал свойство? Единственный способ состоит в том, чтобы опросить собственность снова и снова, чтобы проверить, не изменилась ли она. Конечно, вы можете решить эту проблему, внедрив INotifyPropertyChanged, но опять же вы вернетесь к событиям!

2 голосов
/ 26 августа 2009

События являются частным случаем шаблона Inversion of Control (IoC). Традиционный поток управления, вызывающая сторона вызывает метод для вызываемого (как вы предлагаете). С IoC (и, следовательно, событиями) мы меняем элемент управления приложения и вместо того, чтобы сообщать вызываемому, что делать, мы сообщаем вызывающему уведомлять нас, когда происходит что-то, в чем мы заинтересованы.

Рассмотрим случай таймера . Я хочу получать уведомления каждые 5 секунд (скажем). Я не хочу постоянно опрашивать таймер ("время уже пришло? Время пришло? Время пришло?"). Вместо этого я хочу инвертировать управление потоком моего приложения. Я хочу сказать таймеру: «Когда придет время, сообщите мне, вызвав этот метод». Таким образом, управление «инвертируется», вызываемый вызывает метод для вызывающего!

Рассмотрим следующий код ...

using System;
using System.Timers;

namespace TestTimer
{
    class Program
    {
        static void Main(string[] args)
        {
            // create my timer.
            var t = new System.Timers.Timer(1000);

            // register for notification
            // tell the timer, "when it's time, call TimerGoesOff method"
            t.Elapsed += new ElapsedEventHandler( TimerGoesOff );

            // start the timer
            t.Start();

            // wait
            Console.ReadLine();
        }

        // this gets called when the timer goes off
        public static void TimerGoesOff(object source, ElapsedEventArgs e)
        {
            Console.WriteLine("The Time is " + e.SignalTime);
        }
    }
}

Вместо того, чтобы вызывать метод таймера, чтобы спросить, когда он снова сработает (как вы предлагаете), я говорю ему: «когда вы уйдете, вызовите метод TimerGoesOff». Теперь, вместо того, чтобы просто ждать, пока Таймер сработает, я мог бы поработать. Рассмотрим этот код ...

using System;
using System.Threading;
using System.Timers;

namespace TestTimer
{
    class Program
    {
        static void Main(string[] args)
        {
            // create my timer.
            var t = new System.Timers.Timer(1000);

            // register for notification
            t.Elapsed += new ElapsedEventHandler( TimerGoesOff );

            // start the timer
            t.Start();

            // do some work while timer is going
            new Thread(() => DoWork()).Start();

            Console.ReadLine();
        }

        // this gets called when the timer goes off
        public static void TimerGoesOff(object source, ElapsedEventArgs e)
        {
            Console.WriteLine("The Time is " + e.SignalTime);
        }

        public static void DoWork()
        {
            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine( "Working ..." );
                Thread.Sleep( 1000 );
            }
        }
    }
}

Теперь я получаю что-то вроде ...

Working ...
The Time is 8/25/2009 1:05:59 PM
Working ...
Working ...
The Time is 8/25/2009 1:06:00 PM
Working ...
The Time is 8/25/2009 1:06:01 PM
Working ...
The Time is 8/25/2009 1:06:02 PM
The Time is 8/25/2009 1:06:03 PM

Я использовал Timer.Elapsed Event , чтобы изменить поток управления моего приложения. Я могу уйти и сделать работу, пока «жду», пока не сработает событие таймера. Это стало возможным благодаря IoC и Events.

Это особенно заметно (хе-хе) в пользовательских интерфейсах. Я не хочу продолжать спрашивать "сделал ли пользователь что-нибудь еще? Пользователь еще что-нибудь сделал?" (так было раньше, когда). Вместо этого я говорю Controls, например, «когда пользователь нажимает на вас, дайте мне знать». Таким образом, я могу уйти и заняться другими замечательными делами и при этом быть отзывчивым к пользователю.

...