题目
Please don’t cheat, you need to know about event and delegate concept while developing an application in real world.
Concept of event and delegate is confusing sometimes, so this kata is going to target it.
Events and delegates help us to follow SOLID principle and develop loosely coupled application.
It provide us with a communication method (contract with specific signature) between objects which need to be decoupled.
Basically it provides notifier in one objects so that other objects can subscribe to that.
Suppose you have a list of strings containing names. It shows the order of people who has received some messages, and we want to notify them in every three message.
So, we start counting, and every time we count “Peter” for 3rd, 6th, 9th or n*3th times we send him a text message and Email. this is the logic how we chose a name to send a notification.
in this list:
List<string> peopleList = new List<string>()
{
"Peter", "Mike", "Peter", "Bob", "Peter", "Peter", "Bob", "Mike", "Bob", "Peter", "Peter", "Mike", "Bob"
};
First we inform "Peter", then "Bob", then "Peter", then "Mike".
Here is a class that can do it:
··· C charp
public class NotPublisher
{
public void CountMessages(List<string> peopleList)
{
foreach (string person in peopleList)
{
/*if (some logic to count the person for 3, 6, 9, 12 ... times)
{
SendTextMessage(person);
SendEmail(Person)
}*/
}
}
}
The objects and components are tightly coupled here. We notify the user by sending a test message or Email. Then what if we want to add another method to inform users by sending a VoiP message?
We need to create another function here, and it means our application is not easy to extend. We need to recompile and republish the class again.
Task
Your task is to implement the class as a publisher, so text message or Email or VoiP objects can subscribe to it. So, you need to define a delegate, and then define an event based on the delegate.
PersonEventArgs class (based on EventArgs) with Name property(string) is needed to send Name of the person to the subscriber.
ContactNotify is the event handler that you need to implement in the class. Subscriber classes subscribe to this event handler.
You do not need to worry about the subscribers; they generate different types of objects for test cases.
Here is an example code of a subscriber, however you know ”ContactNotify” is the event handler and you don’t need any information about subscriber:
\call the publisher and subscribe
Publisher publisher = new Publisher();
publisher.ContactNotify += TextMessageSend.Send;
publisher.CountMessages(peopleList);
\\send text message
public class TextMessageSend
{
public static void Send(object source, PersonEventArgs e)
{
\\function to send text message
}
}
Enjoy 🙂
代码
using System;
using System.Collections.Generic;
public class PersonEventArgs : EventArgs
{
public string Name;
}
public class Publisher
{
// 定义MyDelegate委托类型
// 要想用在事件当中,C#规定第二个参数的类型必须继承自System.EventArgs类
public delegate void MyDelegate(object sender, PersonEventArgs e);
public event MyDelegate ContactNotify;
public void CountMessages(List<string> peopleList)
{
var dict = new Dictionary<string,int>();
foreach (string person in peopleList)
{
if(!dict.ContainsKey(person)){
dict.Add(person,1);
}
else{
dict[person]++;
}
if(dict[person]%3==0) {
// ContactNotify的类型是MyDelegate,像调用一个MyDelegate一样调用ContactNotify
this.ContactNotify(null, new PersonEventArgs {Name = person});
}
}
}
}
解题思路
- 第79-83行定义了一个继承自EventArgs的类,因为C#要求这么写才能用在事件里
- 第88行:定义委托,无返回类型,有两个参数(返回类型和参数个数无关)
- 第89行:定义事件,类型是我们定义的委托的类型
- 第95-103行是用字典来实现统计一个名字出现的次数
- 调用事件
参考资料
https://www.cnblogs.com/zhangchenliang/p/4968779.html
https://docs.microsoft.com/zh-cn/dotnet/csharp/delegates-events
https://docs.microsoft.com/zh-cn/dotnet/csharp/event-pattern