我有以下几行:
var lambdaExpression = Expression.Lambda<Func<ClassOne, bool>>(eq, parameter);
var myList = db.ClassOne.Where(lambdaExpression).ToList();
我想让这些线条变得通用。我的尝试是这样的:
mytype = typeof(ClassOne);
var lambdaExpression = Expression.Lambda<Func<mytype, bool>>(eq, parameter);
var myList = db.mytype.Where(lambdaExpression).ToList();
但我明白了:
'mytype'是一个变量,但用作类型
和
'实体'不包含'mytype'的定义,也没有扩展名 方法'mytype'接受'Entities'类型的第一个参数可能是 发现(您是否缺少using指令或程序集引用?)
如您所见,我想通过变量传递ClassOne的名称。我怎样才能做到这一点?感谢。
答案 0 :(得分:1)
这是我一直用来获得Expression<Func<type1, type2>>
的方法。这是反思的力量:
public static MethodInfo GetLambdaExpressionMethod(Type type1, Type type2)
{
return typeof(Expression).GetMethods().Where(x => x.Name == "Lambda").First()
.MakeGenericMethod(typeof(Func<,>).MakeGenericType(type1, type2));
}
您可以使用它,如下所示:
var lambda = GetLambdaExpressionMethod(yourType, typeof(bool)).Invoke(null,
new object[] {
eq,
new ParameterExpression[] { parameter }
});
现在将lambda变量(现在是对象)转换为yourType的Expression<Func<yourType, bool>>
答案 1 :(得分:1)
非常简单:
public class ClassOne
{
public int ID { get; set; }
}
然后我们可以:
public static class MyWhereHelper
{
public static readonly MethodInfo WhereMethod = typeof(MyWhereHelper).GetMethod("Where", BindingFlags.Static | BindingFlags.Public);
public static List<T> Where<T>(IQueryable<T> baseQuery, Expression<Func<T, bool>> where)
{
return baseQuery.Where(where).ToList();
}
}
然后我们使用它:
// Sample data
var db = new
{
Data = new[]
{
new ClassOne { ID = 1 },
new ClassOne { ID = 2 },
new ClassOne { ID = 3 },
}.AsQueryable(),
};
var mytype = typeof(ClassOne);
// Real code begins here
var parameter = Expression.Parameter(mytype);
var eq = Expression.Equal(Expression.Property(parameter, "ID"), Expression.Constant(2));
// In truth lambdaExpression is Expression<Func<mytype, bool>>
LambdaExpression lambdaExpression = Expression.Lambda(eq, parameter);
// Search of mytype inside db
// We look for the property that is implementing IQueryable<mytype>
// We could lookup by name if the name is .mytype
var iqueryableMyType = typeof(IQueryable<>).MakeGenericType(mytype);
var prop = db.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public).Single(x => iqueryableMyType.IsAssignableFrom(x.PropertyType));
// db.mytype value
var propValue = prop.GetValue(db);
// MyWhereHelper.Where<mytype>
MethodInfo method = MyWhereHelper.WhereMethod.MakeGenericMethod(mytype);
var myList = (IEnumerable<object>)method.Invoke(null, new object[] { propValue, lambdaExpression });
我们使用反射来查找db.mytype
并执行查询(请注意我们正在使用&#34;技巧&#34;此处:我们尝试将所有需要使用{{1}的内容放入在单个方法中使用泛型参数,并使用反射一次来执行该方法。显然,我是在谈论<mytype>
)。
在MyWhereHelper.Where<>
内,所有内容都是强类型的。在MyWhereHelper.Where<>
内,我们有一个MyWhereHelper.Where
(即List<T>
)。但是一旦我们退出List<mytype>
,调用者就会在编译时再次知道MyWhereHelper.Where<>
的确切类型,因此它只能将结果操作为{{1} }(或再次使用反射来操纵它)