【发布时间】:2014-09-11 17:34:45
【问题描述】:
我想写如下声明:
Expression<Func<AClass, bool>> filter = x => true;
除了AClass,我想使用在运行时确定的Type 变量。所以,概念上是这样的:
Type aClassType = methodParameter.GetType();
Expression<Func<aClassType, bool>> filter = x => true;
显然语法会有些不同。我假设我需要使用某种反思或其他幻想。
最终目标
这里的最终目标有点复杂,所以我对上面的例子进行了极大的简化。将使用此委托的实际 .Where 调用看起来更像这样:
var copy = iQ;
...
copy = copy.Where( p1 => iQ.Where( p2 => pgr2.Key == p1.Key && p2.DataField == column.DataField && p2.ColumnText.Contains( requestValue ) ).Any() );
p1和p2的所有属性都是IQueryableiQ元素类型的父类的属性。我要创建的 Type 变量将是 iQ 的实际元素类型,即子类。
我该怎么做?
当前进展
根据下面的答案,我编写了这个测试代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace IQueryableWhereTypeChange {
class Program {
static void Main( string[] args ) {
var ints = new List<ChildQueryElement>();
for( int i = 0; i < 10; i++ ) {
ints.Add( new ChildQueryElement() { Num = i, Value = i.ToString() } );
}
IQueryable<ChildQueryElement> theIQ = ints.AsQueryable();
Type type = typeof(ChildQueryElement);
var body = Expression.Constant(true);
var parameter = Expression.Parameter(type);
var delegateType = typeof(Func<,>).MakeGenericType(type, typeof(Boolean));
var lambda = Expression.Lambda( delegateType, body, parameter );
Console.WriteLine( lambda.GetType() );
dynamic copy = theIQ;
Type copyType1 = copy.GetType().GetGenericArguments()[ 0 ];
Type elementType1 = ((IQueryable)copy).ElementType;
Console.WriteLine( "copyType1 : " + copyType1.ToString() );
Console.WriteLine( "elementType1 : " + elementType1.ToString() );
copy = Queryable.Where( copy, lambda );
Type copyType2 = copy.GetType().GetGenericArguments()[ 0 ];
Type elementType2 = ((IQueryable)copy).ElementType;
Console.WriteLine( "copyType2 : " + copyType2.ToString() );
Console.WriteLine( "elementType2 : " + elementType2.ToString() );
}
}
public class ParentQueryElement {
public int Num { get; set; }
}
public class ChildQueryElement : ParentQueryElement {
public string Value { get; set; }
}
}
那个程序有这个输出:
System.Linq.Expressions.Expression`1[System.Func`2[IQueryableWhereTypeChange.ChildQueryElement,System.Boolean]]
copyType1 : IQueryableWhereTypeChange.ChildQueryElement
elementType1 : IQueryableWhereTypeChange.ChildQueryElement
Unhandled Exception:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:
The best overloaded method match for
'System.Linq.Queryable.Where<IQueryableWhereTypeChange.ChildQueryElement>(
System.Linq.IQueryable<IQueryableWhereTypeChange.ChildQueryElement>,
System.Linq.Expressions.Expression<System.Func<IQueryableWhereTypeChange.ChildQueryElement,bool>>
)'
has some invalid arguments
at CallSite.Target(Closure , CallSite , Type , Object , LambdaExpression )
at System.Dynamic.UpdateDelegates.UpdateAndExecute3[T0,T1,T2,TRet](CallSite site, T0 arg0, T1 arg1, T2 arg2)
at IQueryableWhereTypeChange.Program.Main(String[] args)
在我尝试复制我的复杂谓词之前,我想先完成这项工作。
我发现异常令人费解,因为lambda.GetType() 的输出几乎完全匹配异常中的类型。唯一的区别是 System.Boolean 与 bool,但这无关紧要。
【问题讨论】:
标签: c# linq types expression