修改Linq以消除重复性 [英] Modifying Linq to remove repetitiveness
问题描述
private readonly IRepository<Order> _orderRepo; // initialized in the constructor
IRepository<Order> GetOrder(string orderstate)
{
if(orderstate == null)
{
return null;
}
IQueryable<Order> query = null;
if(orderstate == "OrderStateChanged")
{
query = (from c in _orderRepo.Table
where c.OrderStateChanged != 0
select c
);
}
else if (orderstate == "PaymentStateChanged")
{
query = (from c in _orderRepo.Table
where c.PaymentStateChanged != 0
select c
);
}
/*More else if statement*/
}
我使用LINQ从存储库中提取数据,并且还有更多if语句.我想删除代码的重复行为. 我有一个提示"Expression Tree",但是我不明白如何在代码中使用它,或者建议我以其他方式删除它 重复性.
如果您确实要防止手动将orderState
映射到成员(使用if/else
,switch
,IDictionary
,...),您唯一的选择实际上就是表达式树:
var orderType = typeof(Order);
var param = Expression.Parameter(orderType);
var member = orderType.GetMember(orderState).FirstOrDefault();
if (member == null)
{
/* requested member of "Order" does not exist */
}
var filter = Expression.Lambda<Func<Order, bool>>( // "param => param.member != 0"
Expression.NotEqual( // "param.member != 0"
Expression.MakeMemberAccess(param, member), // "param.member"
Expression.Constant(0)), // "0"
param); // "param =>"
query = _orderRepo.Table.Where(filter);
替代(更简单,但如果成员不存在,则抛出ArgumentException
)
var orderType = typeof(Order);
var param = Expression.Parameter(orderType);
var member = Expression.PropertyOrField(param, orderState); // may throw ArgumentException!
var filter = Expression.Lambda<Func<Order, bool>>(
Expression.NotEqual(member, Expression.Constant(0)),
param);
query = _orderRepo.Table.Where(filter);
这样,即使Order
的对象布局发生了变化,您实际上还是通用的.一个缺点当然是存在无效的orderState
值导致Order
成员不存在的风险,但是我确信无论如何您已经有了某种机制.
进一步阅读
private readonly IRepository<Order> _orderRepo; // initialized in the constructor
IRepository<Order> GetOrder(string orderstate)
{
if(orderstate == null)
{
return null;
}
IQueryable<Order> query = null;
if(orderstate == "OrderStateChanged")
{
query = (from c in _orderRepo.Table
where c.OrderStateChanged != 0
select c
);
}
else if (orderstate == "PaymentStateChanged")
{
query = (from c in _orderRepo.Table
where c.PaymentStateChanged != 0
select c
);
}
/*More else if statement*/
}
I used LINQ to extract data from the repo and I have more else if statement. I want to remove the repetitive behavior of my code. I have a clue "Expression Tree" but I can't understand How can I use that in my code Or suggest me any other way to remove repetitiveness.
If you really want to prevent manually mapping orderState
to members (using if/else
, switch
, IDictionary
, ...), your only option are indeed expression trees:
var orderType = typeof(Order);
var param = Expression.Parameter(orderType);
var member = orderType.GetMember(orderState).FirstOrDefault();
if (member == null)
{
/* requested member of "Order" does not exist */
}
var filter = Expression.Lambda<Func<Order, bool>>( // "param => param.member != 0"
Expression.NotEqual( // "param.member != 0"
Expression.MakeMemberAccess(param, member), // "param.member"
Expression.Constant(0)), // "0"
param); // "param =>"
query = _orderRepo.Table.Where(filter);
Alternative (simpler, but throws ArgumentException
if the member doesn't exist)
var orderType = typeof(Order);
var param = Expression.Parameter(orderType);
var member = Expression.PropertyOrField(param, orderState); // may throw ArgumentException!
var filter = Expression.Lambda<Func<Order, bool>>(
Expression.NotEqual(member, Expression.Constant(0)),
param);
query = _orderRepo.Table.Where(filter);
This way you are really generic, even if the object layout of Order
changes. One disadvantage is of course the risk of invalid orderState
values leading to non-existing members of Order
but I'm sure you had some kind of mechanism already, anyway.
Further reading
MSDN - How to: Use Expression Trees to Build Dynamic Queries
CodeProject - Expression Tree Basics
这篇关于修改Linq以消除重复性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!