使用Spring.net表达式语言简化接口
今天偶尔浏览同事写的一段代码,发现在只是为了按照不同属性值从一个对象集合中查询就写了不少方法,考虑了下,结合Spring.net表达式语言,利用其表达式语言对列表投影和选择的支持能有效减少一些不必要的查询接口。
于是写了个简单的示例
场景:系统初始化的时候将用户信息批量加载,之后对用户信息的访问都从缓存中获取。业务会按照根据用户的属性进行查询。
public class User
{
string _Name;
string _AreaCode;
int _Age;
int _Gender;
public string Name
{
get { return _Name; }
set { _Name = value; }
}
public string AreaCode
{
get { return _AreaCode; }
set { _AreaCode = value; }
}
public int Age
{
get { return _Age; }
set { _Age = value; }
}
public int Gender
{
get { return _Gender; }
set { _Gender = value; }
}
}
public class ObjectCollection<T>
{
private System.Collections.Generic.List<T> _Users;
public List<T> Items
{
get { return _Users; }
set { _Users = value; }
}
}
ObjectCollection用来存储User对象,系统初始化的时候会将User实例从数据库中全部取出放在ObjectCollection中并静态化,实现简单的缓存功能,实际应用中User对象可能并不适合一次性缓存,更合适的是Schema类信息,此处只是个示例。
按照同事原来的写法,查询用户信息提供了一组方法,例如:
GetAllUsers - 获取所有用户列表
GetUserByName - 按照指定姓名获取用户信息
GetUserByAreaCode - 获取指定地区的用户列表
...
这些方法的功能其实差不多,都是按照User对象的属性对ObjectCollection进行过滤。如果过滤的时候是从数据库实时获取会比较简单,传入个sql的where语句就行了,那么这些方法可以合并成一个 - GetUsersByCon(string condition)
或者如果使用DataTable缓存数据也可以利用.net的支持使用类sql的where语句进行filter,但是从一个对象集合里filter就麻烦多了,利用spring.net 的expression language,可以方便的进行filter。只要引用下载spring.net,引用spring.core.dll即可。
只需要一个方法
public IList GetObjectsByCondition(ObjectCollection<User> objects,string condition)
{
string query = "Items.?{" + condition + "}";
return (IList)ExpressionEvaluator.GetValue(objects, query);
}
测试的示例如下:
string condition ="";
ObjectCollection<User> Objs= new ObjectCollection<User>();
List<User> userList = new List<User>();
userList.Add(
new User(){Age=20,AreaCode = "340100",Name = "张三",Gender = 1}
);
userList.Add(
new User() { Age = 20, AreaCode = "340101", Name = "张三他哥", Gender = 1 }
);
userList.Add(
new User() { Age = 25, AreaCode = "340100", Name = "李四", Gender = 1 }
);
userList.Add(
new User() { Age = 30, AreaCode = "340200", Name = "李四他姐", Gender = 0 }
);
Objs.Items = userList;
IList list = GetObjectsByCondition(Objs , con);
condition 可以是
Name=='张三'
AreaCode=='340100' and Gender==1
AreaCode in ('340100','340101')
AreaCode like '34*'
..
把以上代码封装成公共方法 IList<T> GetObjectsByCondition(ObjectCollection<T> t,string condition
是不是和Sql的语法很像?只是在处理等于的时候表达式用了 “==”,如果能和sql保持一致就好了。