[英]How can I simplify Linq extension method invokation using reflection?
Background: 背景:
I have a web service that returns the rows in a table (table name supplied as a parameter) with Ids greater than a certain Id (also supplied as a parameter). 我有一个Web服务,它返回表中的行(作为参数提供的表名),其ID大于某个Id(也作为参数提供)。 We are assuming the Ids are sequential. 我们假设Ids是顺序的。
I am using Linq to SQL for database interaction so I want to return the new rows as: 我使用Linq to SQL进行数据库交互,所以我想将新行返回为:
List<WhateverObject>
Because we only know the table name at runtime, I can't use Linq in a normal fashion which has made things much more complex. 因为我们只在运行时知道表名,所以我不能以正常的方式使用Linq,这使得事情变得更加复杂。
Question: 题:
The code is below (and it works). 代码如下(并且有效)。 How can I simplify it? 我该如何简化它? It seems overly complex. 这似乎过于复杂。
private object GetUpdateList(string tableName, int Id, DataClassesDataContext db)
{
PropertyInfo pi = db.GetType().GetProperty(tableName);
var table = pi.GetValue(db, null);
// Get type of object within the table.
Type genericType = table.GetType().GetGenericArguments()[0];
// The Where method lives on the Enumerable type in System.Linq
var whereMethods = typeof(System.Linq.Enumerable)
.GetMethods(BindingFlags.Static | BindingFlags.Public)
.Where(mi => mi.Name == "Where");
// There are actually 2 where methods - we want the one with 2 parameters
MethodInfo whereMethod = null;
foreach (var methodInfo in whereMethods)
{
var paramType = methodInfo.GetParameters()[1].ParameterType;
if (paramType.GetGenericArguments().Count() == 2)
{
// we are looking for Func<TSource, bool>, the other has 3
whereMethod = methodInfo;
break;
}
}
Func<object, bool> IdEquals = BuildEqFuncFor("Id", Id);
whereMethod = whereMethod.MakeGenericMethod(genericType);
var result = whereMethod.Invoke(table, new object[] { table, IdEquals });
MethodInfo toListMethod = typeof(System.Linq.Enumerable).GetMethod("ToList").MakeGenericMethod(genericType);
return toListMethod.Invoke(result, new object[] { result });
}
// Build lambda expression for use in Linq
private static Func<object, bool> BuildEqFuncFor(string prop, object val)
{
// We know we are comparing integers here so cast them.
// There is probably a more general solution.
return t => (int)t.GetType().InvokeMember(prop, BindingFlags.GetProperty, null, t, null) > (int)val;
}
To come up with this solution I have had to reference the following questions: 要想出这个解决方案,我不得不参考以下问题:
Try something like this: 尝试这样的事情:
private IList GetUpdateList(string tableName, int id, DataClassesDataContext db)
{
System.Reflection.PropertyInfo pi = db.GetType().GetProperty(tableName);
var table = pi.GetValue(db, null);
// Get type of object within the table.
Type genericType = table.GetType().GetGenericArguments()[0];
var param = Expression.Parameter(genericType, "x");
var predicateExpr = Expression.Lambda(
Expression.GreaterThan(
Expression.Property(param, "Id"),
Expression.Constant(id)),
param);
return this
.GetType()
.GetMethod("GetUpdateListGeneric")
.MakeGenericMethod(genericType)
.Invoke(this, new[] { table, predicateExpr }) as IList;
}
private IList<T> GetUpdateListGeneric<T>(
Table<T> table,
Expression<Func<T, bool>> predicate) where T : class
{
return table.Where(predicate).ToList();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.