当前位置:  开发笔记 > 编程语言 > 正文

你会如何重构这个LINQ代码?

如何解决《你会如何重构这个LINQ代码?》经验,为你挑选了2个好方法。

我有很多丑陋的代码,看起来像这样:

if (!string.IsNullOrEmpty(ddlFileName.SelectedItem.Text))
    results = results.Where(x => x.FileName.Contains(ddlFileName.SelectedValue));
if (chkFileName.Checked)
    results = results.Where(x => x.FileName == null);

if (!string.IsNullOrEmpty(ddlIPAddress.SelectedItem.Text))
    results = results.Where(x => x.IpAddress.Contains(ddlIPAddress.SelectedValue));
if (chkIPAddress.Checked)
    results = results.Where(x => x.IpAddress == null);

...etc.

results是一个IQueryable.
我们的想法是,对于这些无数下拉列表和复选框中的每一个,如果下拉列表中选择了某些内容,则用户希望匹配该项目.如果选中该复选框,则用户特别需要该字段为空或空字符串的那些记录.(UI不允许同时选择它们.)这一切都添加到LINQ表达式,在我们添加了所有条件之后,它将在最后执行.

看起来像,就必须有某种方式拉出一个Expression>或两个,这样我可以把重复部分的方法,只是在传递什么样的变化.我在其他地方做过这个,但这套代码让我受阻.(另外,我想避免使用"动态LINQ",因为我希望尽可能保持类型安全.)任何想法?



1> Keith..:

我将它转换为单个Linq语句:

var results =
    //get your inital results
    from x in GetInitialResults()
    //either we don't need to check, or the check passes
    where string.IsNullOrEmpty(ddlFileName.SelectedItem.Text) ||
       x.FileName.Contains(ddlFileName.SelectedValue)
    where !chkFileName.Checked ||
       string.IsNullOrEmpty(x.FileName)
    where string.IsNullOrEmpty(ddlIPAddress.SelectedItem.Text) ||
       x.FileName.Contains(ddlIPAddress.SelectedValue)
    where !chkIPAddress.Checked ||
       string.IsNullOrEmpty(x. IpAddress)
    select x;

它并不短,但我发现这个逻辑更清晰.



2> Keith..:

在这种情况下:

//list of predicate functions to check
var conditions = new List> 
{
    x => string.IsNullOrEmpty(ddlFileName.SelectedItem.Text) ||
         x.FileName.Contains(ddlFileName.SelectedValue),
    x => !chkFileName.Checked ||
         string.IsNullOrEmpty(x.FileName),
    x => string.IsNullOrEmpty(ddlIPAddress.SelectedItem.Text) ||
         x.IpAddress.Contains(ddlIPAddress.SelectedValue),
    x => !chkIPAddress.Checked ||
         string.IsNullOrEmpty(x.IpAddress)
}

//now get results
var results =
    from x in GetInitialResults()
    //all the condition functions need checking against x
    where conditions.All( cond => cond(x) )
    select x;

我只是显式声明了谓词列表,但是可以生成这些,例如:

ListBoxControl lbc;
CheckBoxControl cbc;
foreach( Control c in this.Controls)
    if( (lbc = c as ListBoxControl ) != null )
         conditions.Add( ... );
    else if ( (cbc = c as CheckBoxControl ) != null )
         conditions.Add( ... );

你需要一些方法来检查你需要检查的MyClass的属性,为此你必须使用反射.

推荐阅读
Chloemw
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有