在写WPF教程的MVVM篇章时,会碰到接口INotifyPropertyChanged,里面只有 一个event PropertyChangedEventHandler PropertyChanged事件,因此引申出本章。
可以在接口中声明事件,然后在类中实现该事件的引用。在为方法订阅事件时,可以订阅接口声明的事件,也可以订阅类中的事件。我们看下面这个例子。
public class CustomEventArgs : EventArgs
{
private double area;
public double Area
{
get { return area; }
set { area = value; }
}
public CustomEventArgs(double a)
{
area = a;
}
}
public interface IDrawingObject
{
event EventHandler<CustomEventArgs> ShapeChanged;//定义一个标准事件
}
public class Shape : IDrawingObject
{
public event EventHandler<CustomEventArgs> ShapeChanged;
public void RaiseEvent()//事件触发器
{
OnShapeChanged(new CustomEventArgs(10));//触发事件
}
protected virtual void OnShapeChanged(CustomEventArgs e)
{
if (ShapeChanged != null)
{
ShapeChanged(this, e);
}
}
}
class Program
{
static private void HandlerShapeChanged(object sender,EventArgs e)
{
CustomEventArgs msg=e as CustomEventArgs;
Console.WriteLine(msg.Area);
}
static void Main(string[] args)
{
Shape s = new Shape();
IDrawingObject ido = s;
//为HandlerShapeChanged方法订阅接口中声明的事件
ido.ShapeChanged += HandlerShapeChanged;
//为HandlerShapeChanged方法订阅实现接口的事件
//s.ShapeChanged += HandlerShapeChanged;
s.RaiseEvent();
Console.Read();
}
}
我们深挖函数源码会发现很多地方会用事件访问器,这里 不妨顺带研习一下。
事件访问器类似属性访问器,事件访问器被命名为add和remove,一般情况下不需提供自定义事件访问器,因为在编译时会自动添加事件访问器。
1.add事件访问器:当客户端订阅该事件,调用该访问器。
2.remove事件访问器:当客户端取消订阅事件,调用该访问器。
我们现在对上面例子进行改造,用add和remove访问器来删减事件。Events类来替换Shape类,并且注意入口函数里的注释。
public class Events : IDrawingObject
{
public event EventHandler<CustomEventArgs> ShapeChanged;
public event EventHandler<CustomEventArgs> IDrawingObj
{
add
{
ShapeChanged += value;
}
remove
{
try
{
lock (ShapeChanged)//lock对象不能为null
{
ShapeChanged -= value;
}
}
catch { Console.WriteLine("对象为null"); }
}
}
public void Raise(CustomEventArgs e)
{
try
{
ShapeChanged(this, e);
}
catch { }
}
}
static void Main(string[] args)
{
Events s = new Events();
s.IDrawingObj += HandlerShapeChanged;
//s.IDrawingObj -= HandlerShapeChanged;//注掉为ShapeChanged为null
//s.IDrawingObj -= HandlerShapeChanged;//注掉lock (ShapeChanged)报错,预先加try{} catch
s.Raise(new CustomEventArgs(10));
Console.Read();
}
总结
接口可以放事件,善于或用借口和事件,让代码更加美观。