-
-
- 1.发布者和订阅者
- 2.声明事件
- 3.订阅事件
- 4.触发事件
- 5.标准事件用法
- 5.1 通过扩展EventArgs来传递数据
- 5.2 移除事件处理程序
- 6.事件访问器
-
1.发布者和订阅者
- 发布者(publisher) 发布某个事件的类或结构,其他类可以在该事件发生时得到通知
- 订阅者(subscriber) 注册并在事件发生时得到通知的类或结构。
- 事件处理程序(event handler) 由订阅者注册到事件的方法,在发布者触发事件后执行。
- 触发(raise)事件 调用(invoke)或触发(fire)事件的术语,当事件触发时,所有注册到它的方法依次调用。 事件包含了一个私有的委托。
2.声明事件
- 事件声明在一个类中
- 事件需要委托类型的名称,任何附加到事件(如注册)的处理程序都必须与委托类型的签名和返回类型匹配
- 事件声明为public,这样其他类或结构才可以在上面注册
- 不能使用new表达式创建事件对象
class Incrementer
{
public event EventHandler publish;
}
可以使用逗号分隔多个事件声明,
public event EventHandler MyEvent1, MyEvent1, MyEvent1;
还可以使用static关键字让事件变成静态的,
public static event EventHandler MyEvent;
事件是类或结构的成员,所以有以下几条特性:
- 不能在一段可执行代码中声明事件
- 必须声明在类或结构中
- 事件成员隐式自动初始化为null
3.订阅事件
使用+=运算符来为事件增加事件处理程序
Incrementer i = new Incrementer();
Incrementer.EventHandler += i.Method1; //方法引用形式
Incrementer.EventHandler += StaticClass.Method2; //方法引用形式
i.EventHandler += new MyDel(i2.Method3); // 委托形式
Incrementer.EventHandler += () => count++; // Lambda表达式
Incrementer.EventHandler += delegate { count++ }; // 匿名方法
4.触发事件
- 在触发事件前与null进行比较,查看是否包含事件处理程序
if(EventHandler != null)
{
Eventhandler(param1, param2);
}
将事件声明和触发事件的代码放在一起就有了发布者类的声明。
delegate void Handler();
class Incrementer
{
public event Handler CountedADozen;
public void DoCount()
{
for(int i = 1;i < 100;i++)
{
if(i % 12 == 0 && CountedADozen != null)
{
CountedADozen();
}
}
}
}
class Dozens
{
public int DozensCount { get; set; }
public Dozens(Incrementer incrementer)
{
DozensCount = 0;
incrementer.CountedADozen += IncrementDozensCount;
}
void IncrementDozensCount()
{
DozensCount++;
}
}
class Program
{
static void Main()
{
Incrementer incrementer = new Incrementer();
Dozens dozens = new Dozens(incrementer);
incrementer.DoCount();
Console.WriteLine($"Number of dozens = {dozens.DozensCount}");
Console.ReadKey();
}
}
output
Number of dozens = 8
5.标准事件用法
delegate void EventHandler(object sender, EventArgs e); //使用系统定义的Eventhandler委托
class Incrementer
{
public event EventHandler CountedADozen;
public void DoCount()
{
for(int i = 1;i < 100;i++)
{
if(i % 12 == 0 && CountedADozen != null)
{
CountedADozen(this, null); // 触发事件时使用EventHandler的参数
}
}
}
}
class Dozens
{
public int DozensCount { get; set; }
public Dozens(Incrementer incrementer)
{
DozensCount = 0;
incrementer.CountedADozen += IncrementDozensCount; // 添加事件处理程序
}
void IncrementDozensCount(object source, EventArgs e) // 事件处理程序的签名必须与委托的签名匹配
{
DozensCount++;
}
}
class Program
{
static void Main()
{
Incrementer incrementer = new Incrementer();
Dozens dozens = new Dozens(incrementer);
incrementer.DoCount();
Console.WriteLine($"Number of dozens = {dozens.DozensCount}");
Console.ReadKey();
}
}
5.1 通过扩展EventArgs来传递数据
为了向事件处理程序的第二个参数传入数据,需要声明一个派生自EventArgs的自定义类。
public class IncrementerEventArgs : EventArgs
{
public int IterationCount { get; set; }
}
之后使用泛型委托EventHandler<>,
public event EventHandler<IncrementerEventArgs> CountedADozen;
public class IncrementerEventArgs : EventArgs
{
public int IterationCount { get; set; }
}
delegate void EventHandler<T>(object sender, T e);
class Incrementer
{
public event EventHandler<IncrementerEventArgs> CountedADozen;
public void DoCount()
{
IncrementerEventArgs args = new IncrementerEventArgs();
for (int i = 1;i < 100;i++)
{
if(i % 12 == 0 && CountedADozen != null)
{
args.IterationCount = i;
CountedADozen(this, args);
}
}
}
}
class Dozens
{
public int DozensCount { get; set; }
public Dozens(Incrementer incrementer)
{
DozensCount = 0;
incrementer.CountedADozen += IncrementDozensCount;
}
void IncrementDozensCount(object source, IncrementerEventArgs e)
{
Console.WriteLine($"Incremented at iteration: {e.IterationCount} in {source.ToString()}");
DozensCount++;
}
}
class Program
{
static void Main()
{
Incrementer incrementer = new Incrementer();
Dozens dozens = new Dozens(incrementer);
incrementer.DoCount();
Console.WriteLine($"Number of dozens = {dozens.DozensCount}");
Console.ReadKey();
}
}
output
Incremented at iteration: 12 in Incrementer
Incremented at iteration: 24 in Incrementer
Incremented at iteration: 36 in Incrementer
Incremented at iteration: 48 in Incrementer
Incremented at iteration: 60 in Incrementer
Incremented at iteration: 72 in Incrementer
Incremented at iteration: 84 in Incrementer
Incremented at iteration: 96 in Incrementer
Number of dozens = 8
5.2 移除事件处理程序
class Publisher
{
public event EventHandler SimpleEvent;
public void RaiseTheEvent() { SimpleEvent(this, null); }
}
class Subscriber
{
public void MethodA(object o, EventArgs e) { Console.WriteLine("AAA"); }
public void MethodB(object o, EventArgs e) { Console.WriteLine("BBB"); }
}
class Program
{
static void Main()
{
Publisher p = new Publisher();
Subscriber s = new Subscriber();
p.SimpleEvent += s.MethodA;
p.SimpleEvent += s.MethodB;
p.RaiseTheEvent();
Console.WriteLine("Remove MethodB");
p.SimpleEvent -= s.MethodB; // 移除事件处理程序
p.RaiseTheEvent();
Console.ReadKey();
}
}
output
AAA
BBB
Remove MethodB
AAA
6.事件访问器
要改变两个运算符+=和-=的操作,可以为事件定义事件访问器。
public event EventHandler CountedADozen
{
add {...}
remove {...}
}
class Program
{
static void Main(string[] args)
{
Publishser p = new Publishser();
p.NumberChanged -= Subscriber1.OnNumberChanged;
p.NumberChanged += Subscriber2.OnNumberChanged;
p.NumberChanged += Subscriber3.OnNumberChanged;
p.DoSomething();
Console.ReadKey();
}
}
public delegate string GeneralEventHandler(); // 定义委托
public class Publishser // 定义事件发布者
{
private GeneralEventHandler numberChanged; // 声明一个委托变量
public event GeneralEventHandler NumberChanged // 定义事件访问器
{
add // 改变 += 运算符
{
numberChanged = value;
}
remove // 改变 -= 运算符
{
numberChanged = value;
}
}
public void DoSomething()
{
if (numberChanged != null)
{
string rtn = numberChanged();
Console.WriteLine(rtn);
}
}
}
public class Subscriber1 // 定义事件订阅者
{
public static string OnNumberChanged()
{
return "Subscriber1";
}
}
public class Subscriber2
{
public static string OnNumberChanged()
{
return "Subscriber2";
}
}
public class Subscriber3
{
public static string OnNumberChanged()
{
return "Subscriber3";
}
}
output
Subscriber3