Прочитайте Как: публиковать события, соответствующие рекомендациям .NET Framework для получения дополнительной информации о том, как создавать и использовать события.Приведенный здесь пример не так ясен, как следовало бы, поэтому я рассмотрю этот процесс здесь.
Первая часть, необходимая для определения события, - это используемый делегат обработчика события.Это подпись метода, которая требуется всем, кто хочет получать уведомления об этом событии.Как правило, вам не нужно создавать новый делегат самостоятельно, вы должны использовать существующий EventHandler
(или универсальный EventHandler<TEventArgs>
) делегат.Вы бы использовали неуниверсальную версию, если вам не нужно включать какие-либо другие аргументы о событии.В противном случае вы бы использовали общую версию.В вашем случае нет никаких других аргументов, необходимых для события, поэтому вы должны использовать неуниверсальный EventHandler
.
(Если вы хотите иметь возможность включать информацию, такую как старое значениеи новое значение в качестве аргументов, вы будете использовать универсальную версию с соответствующим классом, полученным из EventArgs
. Немного сложной темы, поэтому мы пропустим это.)
Следующая часть должна определить событие.Это так же просто, как если бы вы определяли свойство для своего класса.Разница здесь в том, что вы используете ключевое слово event
, чтобы указать, что вы определяете событие, за которым следует использовать делегат, а также имя события.Соглашение о присвоении имени событию для изменения свойств обычно заключается в шаблоне <i>PropertyName</i>Changed
.Поскольку вам нужно событие, которое вызывается при изменении свойства Name
, вам следует назвать его: NameChanged
.
public event EventHandler NameChanged;
Необязательный (но настоятельно рекомендуемый) шаг - определить методиспользуется для поднятия события.Это поможет вам поднять событие, когда вы хотите.Обычное соглашение об именах похоже на то, как названо событие.На этот раз On<i>EventName</i>
.Так что вы бы назвали это OnNameChanged
здесь.Обычно он определяется как защищенный виртуальный метод, чтобы производные классы могли легко его переопределить.Аргументы функции должны быть аргументами, необходимыми для события.Поскольку здесь нет аргументов, его можно оставить без аргументов в сигнатуре.
Теперь, когда все это на месте, нужно просто вызывать обработчики событий.Это просто делегат, так что просто позвоните.Но не забудьте проверить, если сначала null
, это будет означать, что обработчики событий не были зарегистрированы.Аргументы обработчика должны быть this
(объект, который вызывает событие) и какими бы ни были аргументы.В этом случае аргументов нет, но вы должны вернуть экземпляр «пустого» * 1035 *.
protected virtual void OnNameChanged()
{
EventHandler nameChanged = NameChanged; // always a good idea to store in a local variable
if (nameChanged != null)
{
nameChanged(this, new EventArgs());
}
}
Последняя часть заключается в том, чтобы связать это с вашими свойствами.Вы хотели бы поднять событие, если назначение изменило бы значение свойства.Довольно просто, просто проверьте, отличается ли старое значение от нового.Если это так, измените его и поднимите событие.В противном случае, больше ничего не делать.
private string name;
public string Name
{
get { return name; }
set
{
if (!String.Equals(value, name)) // if the value gets changed...
{
name = value;
OnNameChanged(); // raise the event!!!
}
}
}
Теперь, когда все готово к событию, вы хотите иметь возможность зарегистрировать некоторые обработчики для этого события.Чтобы сделать это, сначала нам понадобится экземпляр Person
, который мы хотим дождаться Name
изменений, и нам нужен метод обработки события с правильной сигнатурой для события.Событие определено для использования делегата EventHandler
, поэтому нам нужен метод с подписью: void NameChanged(object sender, EventArgs e)
.Помните, что аргумент sender
- это объект, вызвавший событие.В данном случае это объект Person
, поэтому мы можем получить измененный объект и проверить свойства, если захотим.Вы можете назвать это как хотите.Шаблон, который я использую лично: <i>InstanceName</i>_<i>EventName</i>
.Поэтому в этом случае я бы назвал его: person_NameChanged
.
static void person_NameChanged(object sender, EventArgs e)
{
Person person = (Person)sender; // cast back to a Person so we can see what's changed
Console.WriteLine("The name changed!");
Console.WriteLine("It is now: " + person.Name); // let's print the name
}
Как только это будет определено, добавьте обработчик к событию, и мы будем уведомлены, если что-то изменится.
person.NameChanged += person_NameChanged;
Если вы хотите, чтобы обработчик был полностью внутри класса, вы можете зарегистрировать событие в классе.Нет необходимости подключать его извне.Вы можете сделать это из конструктора.Я бы не советовал добавлять ваш код в метод генерации событий OnNameChanged()
, этот метод должен быть зарезервирован для простого вызова события.
public Person(string name = "John")
{
this.name = name;
this.NameChanged += builtin_NameChanged;
}
private static void builtin_NameChanged(object sender, EventArgs e)
{
Person person = (Person)sender; // cast back to a Person so we can see what's changed
Console.WriteLine("The name changed!");
Console.WriteLine("It is now: " + person.Name); // let's print the name
}
Обратите внимание, что в этом конкретном примере обработчик является статическим, поэтому он непривязан к одному экземпляру.Это будет работать для любого Person
в целом.Просто имейте в виду, что, поскольку он статический, вы не сможете использовать this
в методе, поэтому необходимо использовать приведение к отправителю.Независимо от того, статично это или нет, зависит от вас, в любом случае все должно быть в порядке.
Итак, все это вместе, вот что вы могли бы сделать:
class Person
{
public Person(string name = "John")
{
this.name = name;
this.NameChanged += builtin_NameChanged;
}
public string Name
{
get { return name; }
set
{
if (!String.Equals(value, name))
{
name = value;
OnNameChanged();
}
}
}
public event EventHandler NameChanged;
protected virtual void OnNameChanged()
{
EventHandler nameChanged = NameChanged;
if (nameChanged != null)
{
nameChanged(this, new EventArgs());
}
}
private static void builtin_NameChanged(object sender, EventArgs e)
{
Person person = (Person)sender;
Console.WriteLine("The name changed!");
Console.WriteLine("It is now: " + person.Name);
}
private string name;
}
class Program
{
static void Main(string[] args)
{
Person person = new Person();
person.Name = "Paul";
}
}