이벤트를 발생하는 방법.
속성의 값이 변경되면 이벤트를 발생하고 처리를 해보자.
event 키워드를 사용하여 이벤트를 선언 하고
이벤트 대리자를(핸들러 메서드 형식) 지정 한다.
public event EventHandler ValueChanged;
대리자는 반환값이 없고(void) 이벤트 발생 객체 와 이벤트 데이터를 인자로 한다.
public delegate void EventHandler(object sender, EventArgs e);
이 형식을 무시해도 되지만 MS 가이드를 따르도록 한다.
이벤트 핸들러가 void가 아니면 의미도 이상하다.
다음은 이벤트 선언과 발생의 코드 이다.
class Item
{
public event EventHandler ValueChanged;
private int value;
public int Value
{
get => this.value;
set
{
if (this.value != value)
{
this.value = value;
OnValueChanged(EventArgs.Empty);
}
}
}
protected virtual void OnValueChanged(EventArgs e)
{
this.ValueChanged?.Invoke(this, e);
}
}
속성 값 Value의 값이 변경 되었을때 이벤트를 발생한다.
Null 조건 연산자를 사용하여 스레드로부터 안전한방식으로 대리자를 호출한다.
상속을 고려하지 않는다면 OnValueChanged 메서드를 전용(private) 으로 작성해도 무관하다.
다음은 이벤트처리 코드 이다.
Item item = new Item();
item.ValueChanged += (s, e) =>
{
Console.WriteLine($"new value: {item.Value}");
};
item.Value = 10;
다음은 조금 수정하여 이벤트 데이터를 사용하여 변경전값과 현재값을 전달한다.
이벤트 데이터 정의:
class ValueChangedEventArgs : EventArgs
{
public int OldValue { get; }
public int NewValue { get; }
public ValueChangedEventArgs(int oldValue, int newValue)
{
this.OldValue = oldValue;
this.NewValue = newValue;
}
}
이벤트 데이터 사용:
class Item
{
public event EventHandler<ValueChangedEventArgs> ValueChanged;
private int value;
public int Value
{
get => this.value;
set
{
if (this.value != value)
{
var oldValue = this.value;
this.value = value;
OnValueChanged(new ValueChangedEventArgs(oldValue, this.value));
}
}
}
protected virtual void OnValueChanged(ValueChangedEventArgs e)
{
this.ValueChanged?.Invoke(this, e);
}
}
이벤트 핸들러에서 데이터 사용:
Item item = new Item();
item.ValueChanged += (s, e) =>
{
Console.WriteLine($"old value: {e.OldValue}, new value: {e.NewValue}");
};
item.Value = 10;
이번에는 여러 속성에서 사용 할 수 있도록 변경 한다.
속성명을 알아내기 위해 CallerMemberName Attribute 를 사용 했다.
수정된 전체 코드:
class PropertyValueChangedEventArgs : EventArgs
{
public string PropertyName { get; }
public object OldValue { get; }
public object NewValue { get; }
public PropertyValueChangedEventArgs(string propertyName, object oldValue, object newValue)
{
this.PropertyName = propertyName;
this.OldValue = oldValue;
this.NewValue = newValue;
}
}
class Item
{
public event EventHandler<PropertyValueChangedEventArgs> PropertyValueChanged;
private int intValue;
public int IntValue
{
get => this.intValue;
set
{
if (this.intValue != value)
{
var oldValue = this.intValue;
this.intValue = value;
OnPropertyValueChanged(oldValue, this.intValue);
}
}
}
private string strValue;
public string StrValue
{
get => this.strValue;
set
{
if (this.strValue != value)
{
var oldValue = this.strValue;
this.strValue = value;
OnPropertyValueChanged(oldValue, this.strValue);
}
}
}
private void OnPropertyValueChanged(
object oldValue, object newValue,
[CallerMemberName] string memberName = "")
{
this.PropertyValueChanged?.Invoke(this, new PropertyValueChangedEventArgs(memberName, oldValue, newValue));
}
}
class Program
{
static void Main(string[] args)
{
Item item = new Item();
item.PropertyValueChanged += (s, e) =>
{
Console.WriteLine($"property name: {e.PropertyName} old value: {e.OldValue}, new value: {e.NewValue}");
};
item.IntValue = 10;
}
}