项目背景, 采用贫血模式, 但希望在使用业务实体机业务规则上的数据属性,使用同一规则。
比如:在页面中, “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 = new EvalService().GetBllValue(bll, data, path); Assert.AreEqual(expect, value); }
原文:http://www.cnblogs.com/iyxqj/p/3840143.html