委托

    在中间件之前,先说一下委托。我自己在日常开发中好像也没怎么用到自定义的委托,不过还是要了解一下,那么委托是什么呢?委托是一种引用类型,如字面意思:在C#里委托就是委托别的方法来实现具体的功能。
借用网上一个例子解释一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public delegate void GreetingDelegate(string name);
class Program
{
private static void EnglishGreeting(string name)
{
Console.WriteLine("Morning, " + name);
}
private static void ChineseGreeting(string name)
{
Console.WriteLine("早上好, " + name);
}
// 将委托类型GreetingDelegate作为形参声明
private static void GreetPeople(string name, GreetingDelegate MakeGreeting)
{
// 这里可以完成其他的业务逻辑
// 然后调用委托
MakeGreeting(name);
}
static void Main(string[] args)
{
// 使用静态方法初始化委托
GreetPeople("hanmeimei", EnglishGreeting);
GreetPeople("韩梅梅", ChineseGreeting);
Console.ReadKey();
}
}

    如上代码,其实简单的理解就是定义声明了委托之后(定义了返回的类型和参数),定义其他参数与委托相同的方法EnglishGreeting、ChineseGreeting,然后将委托类型作为方法GreetPeople的形参,在调用时,将参数和EnglishGreeting、ChineseGreeting方法传到GreetPeople方法里(这里要注意定义的方法的形参要和声明的委托一致),就能将他们关联起来。
    调用者调用委托,委托调用目标方法。
    如果不想额外定义方法,也可以直接实例化委托,然后调用,比如:

1
2
3
4
5
6
// 实例化
GreetingDelegate gd = EnglishGreeting;// 此处是简写,实际上是 GreetingDelegate gd1 = new GreetingDelegate(EnglishGreeting);
// 调用
gd("hanmeimei");// 此处是简写,实际上是 gd.Invoke("hanmeimei");
// 输出结果
// Morning, hanmeimei

    相同类型的委托也可以使用“+”运算符进行合并,“-”运算符移除 -> 多播委托。比如:

1
2
3
4
5
6
7
8
9
10
11
// 实例化
GreetingDelegate gd;
GreetingDelegate gd1 = EnglishGreeting;
GreetingDelegate gd2 = ChineseGreeting;
gd = gd1;
gd += gd2;
// 调用
gd("hanmeimei");
// 输出结果:
// Morning, hanmeimei
// 早上好, hanmeimei

    总体感觉就如同:委托是一个容器,实例化时,将与之匹配的方法扔到容器里,最后调用的时候顺序执行里面的方法。

事件

    事件是一种特殊的委托(受到了一定的限制),在委托上加上关键字event,让事件的触发权限留给事件源,而不是在哪都能调用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
namespace ConsoleApp1
{
class Program
{

static void Main(string[] args)
{
var reader = new Reader();
reader.Read += Print;
reader.Read("Hello"); //..........C
//reader.Run(); //..........D
}

static void Print(string data)
{
Console.WriteLine("Print: " + data);
Console.ReadLine();
}
}
class Reader
{
public delegate void ReadHandler(string key);

public event ReadHandler Read; //..............A
//public ReadHandler Read; //..............B

public void Run()
{
Console.Write("Read: ");
string input = Console.ReadLine();
Read(input);
}
}
}

    在A + C的情况下:使用event关键字,会报错。不允许直接调用事件。其余任何情况是由对象去触发的话,就能成功。