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!!!

姓名:王卯东 英文名:Michael QQ:942352461 Email:armdong@163.com 主要研究方向:javascript,require.js;
原文地址:https://www.cnblogs.com/ARMdong/p/linqparameterizedfunc.html