我该如何清理此lambda?

问题描述

| 我有一个表达式,在多个LINQ查询中使用了几次,因此我将其分离为返回表达式的自己的方法。该函数的lambda部分看起来有些凌乱。任何人都想破解它,使其更具可读性和/或更小?
    private Expression<Func<Message,bool>> UserSelector(string username,bool sent)
    {
        return x => ((sent ? x.FromUser : x.ToUser).Username.ToLower() == username.ToLower()) && (sent ? !x.SenderDeleted : !x.RecipientDeleted);
    }
关于它的作用的快速英文描述是检查布尔值
sent
并基于该布尔值检查
Message.FromUser
Message.ToUser
。 如果用户正在查看他/她的发件箱,则
sent
为真,它将查看
x.FromUser.Username == username
x.SenderDeleted == false
。 如果用户正在查看他/她的收件箱,则它执行相同的逻辑,但发送为false,而是检查
x.ToUser
x.RecipientDeleted
。 也许这是最简单的方法,但是我愿意进行一些重构。 答案编辑 我真的很喜欢Davy8的答案,但我决定更进一步,用两个表达式代替一个带有嵌套函数的表达式。现在,我有以下方法
    /// <summary>
    /// Expression to determine if a message belongs to a user.
    /// </summary>
    /// <param name=\"username\">The name of the user.</param>
    /// <param name=\"sent\">True if retrieving sent messages.</param>
    /// <returns>An expression to be used in a LINQ query.</returns>
    private Expression<Func<Message,bool>> MessageBelongsToUser(string username,bool sent)
    {
        return x => (sent ? x.FromUser : x.ToUser).Username.Equals(username,StringComparison.OrdinalIgnoreCase);
    }

    /// <summary>
    /// Expression to determine if a message has been deleted by the user.
    /// </summary>
    /// <param name=\"username\">The name of the user.</param>
    /// <param name=\"sent\">True if retrieving sent messages.</param>
    /// <returns>An expression to be used in a LINQ query.</returns>
    private Expression<Func<Message,bool>> UserDidNotDeleteMessage(string username,bool sent)
    {
        return x => sent ? !x.SenderDeleted : !x.RecipientDeleted;
    }
所以现在我的查询看起来像这样:
    /// <summary>
    /// Retrieves a list of messages from the data context for a user.
    /// </summary>
    /// <param name=\"username\">The name of the user.</param>
    /// <param name=\"page\">The page number.</param>
    /// <param name=\"itemsPerPage\">The number of items to display per page.</param>
    /// <param name=\"sent\">True if retrieving sent messages.</param>
    /// <returns>An enumerable list of messages.</returns>
    public IEnumerable<Message> GetMessagesBy_Username(string username,int page,int itemsPerPage,bool sent)
    {
        var query = _dataContext.Messages
            .Where(MessageBelongsToUser(username,sent))
            .Where(UserDidNotDeleteMessage(username,sent))
            .OrderByDescending(x => x.SentDate)
            .Skip(itemsPerPage * (page - 1))
            .Take(itemsPerPage);
        return query;
    }

    /// <summary>
    /// Retrieves the total number of messages for the user.
    /// </summary>
    /// <param name=\"username\">The name of the user.</param>
    /// <param name=\"sent\">True if retrieving the number of messages sent.</param>
    /// <returns>The total number of messages.</returns>
    public int GetMessageCountBy_Username(string username,sent))
            .Count();
        return query;
    }
我要说的是一些非常易于阅读的英语查询,谢谢大家! 参考:http://www.codetunnel.com/blog/post/64/how-to-simplify-complex-linq-expressions     

解决方法

将其拆分为一个单独的函数:
    private Expression<Func<Message,bool>> UserSelector(string username,bool sent)
    {
        return message=> InnerFunc(message,username,sent);
    }

    private static bool InnerFunc(Message message,string username,bool sent)
    {
        if(sent)
        {
            return string.Equals(message.FromUser.Username,StringComparison.InvariantCultureIgnoreCase) && !message.SenderDeleted;
        }
        return string.Equals(message.ToUser.Username,StringComparison.InvariantCultureIgnoreCase) && !message.RecipientDeleted;
    }
或者,可以内联它以保持闭包用法:
    private Expression<Func<Message,bool sent)
    {
        Func<Message,bool> innerFunc = message =>
        {
            if (sent)
            {
                return string.Equals(message.FromUser.Username,StringComparison.InvariantCultureIgnoreCase) &&
                        !message.SenderDeleted;
            }
            return string.Equals(message.ToUser.Username,StringComparison.InvariantCultureIgnoreCase) &&
                    !message.RecipientDeleted;
        };
        return message => innerFunc(message);
    }
(经编辑可将ѭ13culture和ѭ14cases用于具有不同区域性设置的奇怪边缘情况。)     ,你有剃须刀吗?很多时候,我会像这样写一些foreach循环,看看Resharper是否可以重构它。尽管可以评估所提出的任何解决方案的性能,但我认为可读性是最重要的。     ,只要您将为该问题写的描述作为评论,它就会帮助尝试阅读/理解它的人正确吗?