我有很多丑陋的代码,看起来像这样:
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",因为我希望尽可能保持类型安全.)任何想法?
我将它转换为单个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;
它并不短,但我发现这个逻辑更清晰.
在这种情况下:
//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的属性,为此你必须使用反射.