修改Linq以消除重复性 [英] Modifying Linq to remove repetitiveness

查看:76
本文介绍了修改Linq以消除重复性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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/elseswitchIDictionary ,...),您唯一的选择实际上就是表达式树:

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成员不存在的风险,但是我确信无论如何您已经有了某种机制.

进一步阅读

MSDN-表达式树

MSDN-如何:使用表达式树构建动态查询

CodeProject-表达式树基础

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 - Expression Trees

MSDN - How to: Use Expression Trees to Build Dynamic Queries

CodeProject - Expression Tree Basics

这篇关于修改Linq以消除重复性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆