WM有约II(六):分级限制

等级制度

  在上一集里,我们把发送查询短信息的人分为"联系人"和"陌生人"两大类,应用程序会自动回复"联系人",忽略"陌生人",在这一集里,我们将会引入另外两种类型:"白名单"和"黑名单"。如果你看过上一集,你应该知道"联系人"和"陌生人"是互斥的,它们之间的区别是手机号码是否存在联系人里。"白名单"和"黑名单"是在"联系人"上发展出来的两个细分类型,它们也是互斥的,"白名单"允许执行所有查询,而"黑名单"则禁止执行所有查询。至于"陌生人",我们将会给它一个"注册"的机会,让它可以请求把自己加到联系人里。这四个等级将会通过AccessLevel枚举来表达:

代码 1

  在这一集里,我们将会在这个"等级制度"的基础上实现如下效果:

访问级别

允许执行的操作

Whitelist

PingStatus、PingSchedule

Contact

PingStatus

Stranger

SignUp

Blacklist

N/A

如何界定访问级别?

  首先,发送方要么在联系人里,要么不在,如果不在,那么他/她的访问级别就是Stranger,如果在,我们还要看看他/她是否在白名单或者黑名单里,如果也在,那么他/她的访问级别就是Whitelist或者Blacklist,否则就是Contact。就实现方式而言,我们应该优先考虑检查白名单和黑名单,因为从集合的角度来看,它们均是联系人的子集,如果发送方在任一名单里,我们就可以立即返回他/她的访问级别,而不必遍历所有联系人,于是,我们可以这样获取发送方的访问级别:

代码 4

  那么,查询操作的访问级别又如何获取呢?我们知道,应用程序(目前)只支持三种查询操作,每种操作所需的最低访问级别如下表所示:

查询操作

所需的最低访问级别

PingStatus

Contact

PingSchedule

Whitelist

SignUp

Stranger*

请把我加为好友……

  下面,我们将会实现SignUp操作。首先,我们要定义这个操作的短信息,很明显,它包含的数据将用于创建Outlook联系人,最低限度应该提供姓名和手机号码:

{Trombone:SignUp(Leehom,Wang,13813572468)}

  用户界面也需要做出相应调整:

图 11

  这个用户界面仅向用户收集姓名,那么,我们如何获取本机的号码?你可以通过P/Invoke调用SmsGetPhoneNumber函数,也可以像我这样,使用OpenNETCF的Smart Device Framework。下载、安装Smart Device Framework 2.3,添加对OpenNETCF.Phone.dll的引用,接着就是修改Ping按钮的代码了(原本的代码参见《WM有约II(四):你明天有空吗?》的代码14):

代码 7

  好了,运行一下看看效果:

图 12

  再来看看Cellular Emulator,很好,注册短信息顺利发出了:

图 13

  接下来就是注册短信息的处理了,因为它只针对陌生人,而且无需自动回复,所以我们不必遵守SmsProcessorBase类的套路,直接让SignUpProcessor类实现ISmsProcessor接口就可以了。在实现SignUpProcessor.Process方法之前,我们需要一个辅助方法来提取注册短信息里的数据:

代码 8

  因为注册短信息的处理需要用户的参与,用户有权决定把发送方添加到联系人还是忽略他/她,所以应用程序应该把截获的注册短信息添加到某个队列里,以便用户过后查询和处理,避免用户在应用程序截获注册短信息时不得不马上处理的尴尬情景。为此,我们需要一个RegistrationQueue来暂存待处理的注册请求,由于每个注册请求都包含了接收时间、姓名和手机号码,于是我们用一个Registration类来存放这些数据:

代码 9

  由于这些数据有可能跨越多个应用程序会话,于是我们需要把它们持久化到文件里,这里我还是选择使用XML:

代码 10

  因为RegistrationQueue的实现和InterceptionHistory(参见《WM有约II(五):区别对待不同的手机号码》)相似,所以我就不在这里一一细说了。

  回到SignUpProcessor.Process方法,在截获注册短信息时,我们需要判断发送方是否陌生人,若是,把相关数据添加到RegistrationQueue,否则,忽略该注册短信息。另外,我们还需要在InterceptionHistory里等级本次截获:

代码 11

  最后,我们需要为此配备一个用户界面:

图 14

  当应用程序启动时,我们要把RegistrationQueue绑定到上面的DataGrid:

代码 12

  当DataGrid上选中的行发生改变时,下面的两个TextBox的内容要更新为当前选中行的姓名:

代码 13

  当用户单击Add按钮时,应用程序将会用当前选中的注册信息来创建Outlook联系人,创建完毕后将会把注册信息从RegistrationQueue里删除:

代码 14

  而当用户单击Remove按钮时,应用程序将会直接把当前选中的注册信息从RegistrationQueue里删除。

好了,又到了测试的时候了(在测试之前,别忘了把SignUpProcessor挂接到InterceptorManager里!),通过Cellular Emulator发送如下注册短信息:

{Trombone:SignUp(Leehom,Wang,13813572468)}

图 15

现在,我们把注意力集中到模拟器上:

图 16

从上图可以看到,注册短信息已被成功截获,单击Add按钮,应用程序将会用选中的注册信息创建Outlook联系人:

图 17

此时,如果我们通过Cellular Emulator使用刚才的手机号码发送如下查询短信息:

{Trombone:PingStatus}

将会收到应用程序的自动回复:

图 18

而主界面上的截获历史也能正确显示发送方的姓名了:

图 19

你还想要什么?

  有一次,我和一个六年级的学生一起看动画片,当我们看到正义的代表向怪兽发动反击时,我问他:"你现在看到这种情节还会觉得体内有一股激动在奔流吗?"他说没有。曾几何时,当我们碰到可以使用新技术的机会时,我们也会异常激动……

  或许,在很多人的眼里,技术只不过是用来解决问题的工具罢了,然而,我更倾向于通过学习/使用技术寻找乐趣。下一集,要不我们试一下db4o吧,然后,再试一下Windows Mobile上的Notification,就是当你收到短信息时屏幕下面弹出的提示框……

NET技术WM有约II(六):分级限制,转载需保留来源!

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。