【发布时间】:2012-01-10 17:33:56
【问题描述】:
我正在尝试创建一个通用 Exists() Command 类,该类能够为我的数据上下文(数据库)中任何 LinqToSQL 类(表)的任何公共属性(字段)组合构造一个 where 子句。
如果基于 MSDN 中的 sn-ps 编写了以下内容,并且发现除非我明确声明 Expression.Lambda 参数的实体类型(在本例中为 MyApp.Data.Organization),否则我无法成功运行代码Expression.Call 语句。
换句话说,
Expression.Lambda<Func<tblType,bool>>(predBody, new ParameterExpression[] { pe }));
不工作,但是,
Expression.Lambda<Func<MyApp.Data.Organization,bool>>(predBody, new ParameterExpression[] { pe }));
确实有效。我想要类似前者的方法,因此该方法对我的数据上下文中的所有 LinqToSQL 类保持通用。
我已经验证了 Expression.Call 语句之前的所有代码都可以正常工作并且会生成正确的谓词。为了保持参数类型的通用性,我需要更改什么,以便相同的代码适用于数据上下文中的任何 LinqToSQL 类?
清晰度修订 似乎我使用 T 作为变量是令人困惑的事情。这是修改后的代码:
OrganizationCriteria criteria = new OrganizationCriteria { OrganizationId = 2 };
using (var ctx = ContextManager<MyApp.Data.MyAppDataContext>.GetManager(myConnectionString, false)) {
IQueryable tbl = ctx.DataContext.GetTable(criteria.EntityType).AsQueryable();
Type tblType = tbl.ElementType;
ParameterExpression pe = Expression.Parameter( tblType, "Item" );
Expression left;
Expression right;
Expression prev = null;
Expression curr = null;
Expression predBody = null;
foreach ( KeyValuePair<string, object> kvp in criteria.StateBag ) {
prev = curr;
object val = kvp.Value;
if (val is System.String ) {
left = Expression.Call( pe, typeof( string ).GetMethod( "ToLower", System.Type.EmptyTypes ) );
right = Expression.Constant( kvp.Value.ToString() );
}
else {
left = Expression.Property( pe, tblType.GetProperty( kvp.Key ) );
right = Expression.Constant( kvp.Value, tblType.GetProperty( kvp.Key ).PropertyType );
}
curr = Expression.Equal( left, right );
if ( prev != null ) {
predBody = Expression.AndAlso( prev, curr );
}
else {
predBody = curr;
}
}
MethodCallExpression whereCall = Expression.Call(
typeof( Queryable ),
"Where",
new Type[] { tblType },
tbl.Expression,
Expression.Lambda<Func<tblType,bool>>(predBody, new ParameterExpression[] { pe }));
var results = tbl.Provider.CreateQuery( whereCall );
}
【问题讨论】:
-
那么, T 是从哪里来的?
-
@BoltClock 他想创建一个接受类型参数
T的方法,所以在创建表达式时无法指定具体的T。 -
答案是使用 Expression.Lambda() 的非泛型重载。因此,将 Expression.Lambda
>(predBody, new ParameterExpression[] { pe }) 替换为 Expression.Lambda(predBody, new ParameterExpression[] { pe }) 就可以了,
标签: c# linq generics lambda expression