利用Func进行重构
你开发中的令人心动的Web2网站的底层数据库中有一张用户表,为了与时俱进,你决定用.NET 3.5呀、LINQ什么的来开发。
在实现自己的MembershipProvider的时候,你发现需要实现依据电子邮件或用户名来查找用户的功能,所以你啪嗒啪嗒地敲出了以下代码:
public User FindByEmail(string email) {
CoolWeb2DataContext db = new CoolWeb2DataContext();
var user = db.Users.SingleOrDefault(u => u.Email == email);
return user;
}
使用Paste & Copy大法,另一个方法呼之即来:
public User FindById(int id) {
CoolWeb2DataContext db = new CoolWeb2DataContext();
var user = db.Users.SingleOrDefault(u => u.UserId == id);
return user;
}
正打算沾沾自喜时,作为一名正在学习重构的用功的程序员,你发现这两段代码有臭臭的重复的味道。将来网站做大了,可能还要实现FindByAge、FindByMSN、FindByQQ等等方法,你可不想每次拷来拷去把相同的逻辑复制多份,毕竟这年头,代码的价值与LOC是不成正比的。
所以,你打算实现一个通用的Find方法:
private User Find(what?) {
User = ...;
return user;
}
你注意到要完成这个伟大的算法,需要告诉它你是要查找一个User类型的对象,并且需要把查找的逻辑给传递进去。马上打开.NET类库寻找,很快就找到了这个东东:
public delegate TResult Func<T, TResult>(T arg);
嗯,这正是我需要的。你嘀咕着,同时把这个Find方法改为:
private User Find(Func<Models.User, bool> predicate) {
CoolWeb2DataContext db = new CoolWeb2DataContext();
var user = db.Users.SingleOrDefault(predicate); //eh, 也许该作些判空什么的事,还是留到用户数上百万再说吧
return user;
}
这下,原来的两个方法都清爽了:
public User FindByEmail(string email) {
return Find(u => u.Email == email);
}
public User FindById(int id) {
return Find(u => u.UserId == id);
}
离这个要轰动全球的网站的发布,又进了一大步,再完成99.7%的代码,就可以Beta了。把代码签入,你开心地吃晚饭去了。