现在的位置: 首页 > 综合 > 正文

通过反射调用泛型参数方法

2013年01月15日 ⁄ 综合 ⁄ 共 2705字 ⁄ 字号 评论关闭

最近在学习EDM,发现LinqPad是一个好东西,可以运行Linq To Sql, Entity SQL Language脚本,但不会用ESql查询功能,始终报错,半天找不到门道,一怒之下决定自己写一个小型的ESql查询器。

 

将比较重要的知识点归纳了一下,贴几段重要的代码,以免下次遗忘。

 

        private void btnRunQuery_Click(object sender, EventArgs e)
        {
            if (cmbEntitySet.SelectedItem == null)
                return;
            Type typeObjectQuery = (cmbEntitySet.SelectedItem as ImageComboBoxItem).Value as Type;
            Type typeEntity = typeObjectQuery.GetGenericArguments()[0];

            using (cdms3Entities ctx = new cdms3Entities())
            {
                //通过反射调用ObjectQuery<T> CreateQuery<T>(string queryString, params ObjectParameter[] parameters);
                MethodInfo miCreateQuery = ctx.GetType().GetMethod("CreateQuery", BindingFlags.Instance | BindingFlags.Public);
                //设置CreateQuery<T>中的T泛型参数为typeEntity所指的实体对象类型
                miCreateQuery = miCreateQuery.MakeGenericMethod(typeEntity);
                //创建调用参数,传入Entity SQL Language语句
                object[] args = new object[] { mmeESql.Text, new ObjectParameter[] { } };
                //调用CreateQuery函数,返回一个ObjectQuery<T>类型的对象,ObjectQuery<T>泛型类由ObjectQuery类派生,所以可转换为ObjectQuery类型
                ObjectQuery oq = miCreateQuery.Invoke(ctx, args) as ObjectQuery;

                //如果下列检查框中有选择需要Include到查询中的实体对象
                if (cmbIncludes.Properties.GetCheckedItems() != "")
                {
                    //获取ObjectQuery<T> Include(string path);函数,注意函数的返回值类型是泛型,但函数并不是泛型,所以不需要也不能对其调用MakeGenericMethod方法
                    MethodInfo miInclude = oq.GetType().GetMethod("Include", BindingFlags.Instance | BindingFlags.Public);
                    foreach (CheckedListBoxItem item in cmbIncludes.Properties.Items)
                    {
                        if (item.CheckState == CheckState.Checked)
                        {
                            EntityObjectInfo eo = item.Value as EntityObjectInfo;
                            args = new object[] { eo.Path };
                            //调用ObjectQuery<T>.Include方法
                            oq = miInclude.Invoke(oq, args) as ObjectQuery;
                        }
                    }
                }

                //下面调用ObjectQuery<T>.ToList()方法来获取查询结果。
                //特别要注意的是ToList()方法是一个扩展方法,方法原型是:public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source);位于System.Linq.Enumerable类
                //所以反射时应当对Enumerable类进行,且该方法为公共静态方法。
                MethodInfo miToList = typeof(Enumerable).GetMethod("ToList", BindingFlags.Static | BindingFlags.Public);
                miToList = miToList.MakeGenericMethod(typeEntity);
                args = new object[] { oq };
                object o = miToList.Invoke(null, args);
                //var q = ctx.CreateQuery<Department>(mmeESql.Text);
                mmeTraceSql.Text = oq.ToTraceString();
                grdResultData.DataSource = o;
            }

        }

 

抱歉!评论已关闭.