Linq学习之路(07) - 使用Linq进行参数化编程step by step
我们在程序中往往需要添加过滤器的功能,检索数据的时候希望按照某些条件进行筛选或者排序,解决方案有很多种,比如拼SQL语句或者进行参数化编程。拼过滤条件是最低级最不安全的一种解决方案,不能很好的表现出面向对象编程的思想,正好本人最近在研究Linq,那么今天本人就使用Linq进行参数化编程,数据源还是参考我前面写的那些文章。
给大家看一下UI:
这里我们希望根据Title检索关键字,PageCount主要是想过滤掉那些不满足条件的Objects,SortOrder主要就是指定按照什么条件进行排序,有升序也有降序。
主要界面就是这样,好吧,下面我们就开始如何一步一步实现这些功能:
step1:初始换窗体
这里我主要讲一下PageCount这个下拉框的初始化,我们设置下拉列表中每个项的显示的名字和与其对应的值,为了让界面变得友好,用户一眼就看出来是什么意思,所以我这里用了KeyValuePair来保存Key/Value,Key是给用户看的,而Value是给我们程序员看的,我们根据Value进行相应的操作。附上代码:
cmbCountFilter.DisplayMember = "Key"; cmbCountFilter.ValueMember = "Value"; cmbCountFilter.DataSource = new KeyValuePair<String, int?>[] { new KeyValuePair<String, int?>("any", null), new KeyValuePair<String, int?>("at least 100", 100), new KeyValuePair<String, int?>("at least 200", 200), new KeyValuePair<String, int?>("at least 300", 300) };
另外,我们还要简单的讲一下用于显示检索结果的控件DataGridView控件,由于我们想让他显示我们自定义的元素,所以我们需要将DataGridView控件的AutoGenerateColumns属性值设置为false,这样我们就能让该控件显示我们自定义的列了,给你也给出代码:
//这里我们只想显示自定义的三列:Title,Publisher,PageCount, //所以我们要把AutoGenerateColumns属性设为false dataGridView1.AutoGenerateColumns = false; dataGridView1.Columns.Clear(); dataGridView1.Columns.Add( new DataGridViewTextBoxColumn() { DataPropertyName = "Title", HeaderText = "Title" }); dataGridView1.Columns.Add( new DataGridViewTextBoxColumn() { DataPropertyName = "PageCount", HeaderText = "Pages" }); dataGridView1.Columns.Add( new DataGridViewTextBoxColumn() { DataPropertyName = "Publisher", HeaderText = "Publisher" });
初始化工作我们就做的差不多了,下面开始我们的第二步:
step2:自定义条件检索QueryByCondition
大多数情况下,检索的条件会很多,如果每个条件都写一个方法,那么会大大的增加我们的代码量,而且方法重用的可能性不大,为了构建重用度非常好的方法,这里我们使用参数化编程,提高方法的重用度,代码量也惊人的变少,也是面向对象编程的初衷。
/// <summary> /// 自定义条件检索 /// </summary> /// <typeparam name="TSortKey">排序规则</typeparam> /// <param name="minPageCount">最小页码</param> /// <param name="titleFilter">标题过滤条件</param> /// <param name="sortSelector">排序条件</param> /// <param name="ascending">是否升序</param> public IEnumerable<Book> QueryByCondition<TSortKey>(int? minPageCount, string titleFilter, Func<Book, TSortKey> sortSelector, Boolean ascending) { IEnumerable<Book> books; books = SampleData.Books; if (minPageCount.HasValue) { books = books.Where(book => book.PageCount >= minPageCount); } if (!String.IsNullOrEmpty(titleFilter)) { books = books.Where(book => book.Title.Contains(titleFilter)); } if (sortSelector != null) { if (ascending) { books = books.OrderBy(sortSelector); } else { books = books.OrderByDescending(sortSelector); } } return books; }
上面这段代码就是我们这个demo里面最核心的代码,我们根据传进来的这些参数进行判断检索,得到我们想要的那些数据。
step3:根据我们在UI界面选择的条件检索我们期望的数据:
/// <summary> /// 数据绑定 /// </summary> public IEnumerable<Book> LoadData() { IEnumerable<Book> books = null; int? minPageCount; string titleFilter; minPageCount = (int?)cmbCountFilter.SelectedValue; titleFilter = txtTitleFilter.Text; switch (cmbSortOrder.SelectedIndex) { case 0: books = QueryByCondition(minPageCount, titleFilter, book => book.Title, true); break; case 1: books = QueryByCondition(minPageCount, titleFilter, book => book.Title, false); break; case 2: books = QueryByCondition(minPageCount, titleFilter, book => book.Publisher.Name, true); break; case 3: books = QueryByCondition(minPageCount, titleFilter, book => book.Publisher.Name, false); break; case 4: books = QueryByCondition(minPageCount, titleFilter, book => book.PageCount, true); break; case 5: books = QueryByCondition(minPageCount, titleFilter, book => book.PageCount, false); break; default: books = QueryByCondition<Object>(minPageCount, titleFilter, null, true); break; } //这里将检索到的books转换为List列表非常重要 //因为Linq中对数据的检索存在Derfferd Query //如果这里没有加上ToList()方法的话,在UI层我们是不会得到结果的 return books.ToList(); }
这段代码主要是根据我们选择的过滤条件和排序规则进行判断,然后传入相应的参数调用QueryByCondition方法。
step4:最后一步,在btn_click事件中调用我们的LoadData方法:
/// <summary> /// 按钮点击事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnSearch_Click(object sender, EventArgs e) { dataGridView1.DataSource = LoadData(); }
好了大功告成了,我们来看看我们的成果:
1、按关键字检索:
2、按最小页码检索:
3、按排序规则检索:
4、组合查询:
5、默认查询:
ok,这篇文章就讲到这里,let's make oop develop better!!!
转载于:https://www.cnblogs.com/ARMdong/archive/2013/05/19/linqparameterizedfunc.html