首页 > 代码库 > 采用表达式树提升属性访问性能

采用表达式树提升属性访问性能

 

项目背景, 采用贫血模式, 但希望在使用业务实体机业务规则上的数据属性,使用同一规则。

比如:在页面中, “RS_Department.Code" , "Department.Code"都可以正常访问。

 

业务实体类

直接使用Linq to Sql 自动生成的代码,跟数据库表一一对应。

如:RS_Requisition, RS_Department

 

业务规则类

实现数据库增删改查,扩展属性,其他业务规则等。

    public class Requisition : BLLTableCodeNameWraper<RS_Requisition>    {        public RS_Department Department(RS_Requisition data)        {                        return data.RS_Department;        }    }

以上只是简单示例, 属性可能需要访问数据库,可能需要缓存数据结果。

 

 如下是通过表达式树实现的代码

    public object GetBllValue(Base.IBLLQuery bll, object data, string path)    {        ParameterExpression bllExpr = Expression.Parameter(bll.GetType(), "bll");        ParameterExpression dataExpr = Expression.Parameter(data.GetType(), "data");        Expression b = bllExpr;        Expression d = dataExpr;        var properties = path.Split(.);        foreach (var property in properties)        {            if (d.Type.GetProperties().Where(p => string.Compare(p.Name, property, true) == 0).Count() > 0)            {                d = MemberExpression.Property(d, property);            }            else if (bll.GetType().GetMethod(property) != null)            {                ///只能调用一次                d = Expression.Call(b, b.Type.GetMethod(property), d);            }        }        ///性能考虑可以缓存Func委托        var c = LambdaExpression.Lambda(d, bllExpr, dataExpr).Compile() ;        return c.DynamicInvoke(bll, data)



测试代码如下:

    [TestMethod]    public void TestBllEval()    {        var bll = new Requisition();        RS_Requisition data = new RS_Requisition();        data.RS_Department = new RS_Department() { DName = "a" };        string path = "Department.DName";        Expression<Func<Requisition, RS_Requisition, object>> e = (p, q) => p.Department(q).DName;        var expect = e.Compile().Invoke(bll, data);                   var value = http://www.mamicode.com/new EvalService().GetBllValue(bll, data, path);        Assert.AreEqual(expect, value);    }