如何让类型参与表达式
本文关键字:表达式 类型 | 更新日期: 2023-09-27 18:06:54
如何获得参与linq表达式的所有类型?我实际上需要这个来缓存查询结果。
在这个例子中很简单:
var Query = (from x in DataContext.Current.ContractDurations select x);
我需要的类型在
中提供Query.ElementType
但是当我这样做时会发生什么呢?
var Query = (from x in DataContext.Current.ContractDurations select x.ID);
ElementType将是int。如果ElementType是某种随机的匿名类型,那么在连接中也会出现同样的问题。
我看不出有什么问题…只要原始数据上下文是IQueryable,就应该可以访问ElementType。
参见以下内容:
void Main()
{
List<Alerts> alerts = new List<Alerts>();
alerts.Add(new Alerts(DateTime.Now.AddDays(-1)));
alerts.Add(new Alerts(DateTime.Now));
IQueryable<Alerts> qAlerts = alerts.AsQueryable();
var query1 = qAlerts.Select (a => a.Begins);
Console.WriteLine(query1.ElementType);
var query2 = qAlerts.Select (a => a);
Console.WriteLine(query2.ElementType);
var query3 = alerts.Select (a => a);
Console.WriteLine(query3.AsQueryable().ElementType);
}
public class Alerts
{
public DateTime Begins {get; set;}
public Alerts(DateTime begins)
{
Begins = begins;
}
}
关键是ElementType是IQueryable成员,因此您需要确保原始源是IQueryable(如query1和query2),或者您将查询强制转换为IQueryable(如query3)。
最后,对于这种事情,拿一个LinqPad的副本…免费版很棒,付费版会让你更有智慧。
public class QueryExpressionVisitor : ExpressionVisitor
{
public List<Type> Types
{
get;
private set;
}
public QueryExpressionVisitor()
{
Types = new List<Type>();
}
public override Expression Visit(Expression node)
{
return base.Visit(node);
}
protected override Expression VisitConstant(ConstantExpression node)
{
if (node.Type.IsGenericTypeDefinition && node.Type.GetGenericTypeDefinition() == typeof(IQueryable<>))
CheckType(node.Type.GetGenericArguments()[0]);
return base.VisitConstant(node);
}
protected override Expression VisitMember(MemberExpression node)
{
CheckType(node.Member.DeclaringType);
return base.VisitMember(node);
}
private void CheckType(Type t)
{
if (!Types.Contains(t))
{
Types.Add(t);
}
}
}