通过反射调用泛型参数方法
最近在学习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;
}
}