C# 从MethodCallExpression获取投影
我有一个带有C# 从MethodCallExpression获取投影,c#,.net,linq,expression-trees,C#,.net,Linq,Expression Trees,我有一个带有select的Linq查询,从我的Linq查询提供程序中,我得到一个包含MethodCallExpression的表达式树,但是我如何从MethodCallExpression中获得select投影呢 internal static object Execute(Expression expression, bool isEnumerable) { var whereExpression = expression as MethodCallExpres
select
的Linq查询,从我的Linq查询提供程序中,我得到一个包含MethodCallExpression
的表达式树,但是我如何从MethodCallExpression
中获得select投影呢
internal static object Execute(Expression expression, bool isEnumerable)
{
var whereExpression = expression as MethodCallExpression;
if (whereExpression == null) throw new InvalidProgramException("Error");
foreach (var arg in whereExpression.Arguments)
{
if (arg is UnaryExpression)
{
var unaryExpression = arg as UnaryExpression;
var lambdaExpression = unaryExpression.Operand as LambdaExpression;
if (lambdaExpression == null) continue;
// Here I would like to get the select projections, in this example the "word" projection ...
查询可能如下所示:
var queryable = new MyQueriableClass();
var query = from thing in queryable
where thing.id == 1
select word;
现在还不清楚你在做什么,但是
// note the AsQueryable! Otherwise there is no
// Expression tree!
var words = new List<string>() { "an", "apple", "a", "day" }.AsQueryable();
// Note that even IQueryable<string> query = words;
// is a perfectly good query without a projection!
// The query
// from word in words where word.Length > 0 select word
// doesn't have a select too (try looking at the
// expression tree... The select has been elided)
// The projection if not present is implicit, the
// whole object.
var query = from word in words
select word;
var exp = query.Expression;
var methodCallExpression = exp as MethodCallExpression;
if (methodCallExpression != null)
{
MethodInfo method = methodCallExpression.Method;
if (method.DeclaringType == typeof(Queryable) && method.Name == "Select")
{
var source = methodCallExpression.Arguments[0];
var selector = methodCallExpression.Arguments[1];
// The selector parameter passed to Select is an
// Expression.Quote(subexpression),
// where subexpression is the lambda expression
// word => word here
if (selector.NodeType != ExpressionType.Quote)
{
throw new NotSupportedException();
}
UnaryExpression unary = (UnaryExpression)selector;
Expression operand = unary.Operand;
if (operand.NodeType != ExpressionType.Lambda)
{
throw new NotSupportedException();
}
LambdaExpression lambda = (LambdaExpression)operand;
// This is the "thing" that returns the result
Expression body = lambda.Body;
}
}
//注意AsQueryable!否则就没有了
//表情树!
var words=new List(){“an”、“apple”、“a”、“day”}.AsQueryable();
//请注意,即使IQueryable查询=单词;
//是一个没有投影的非常好的查询!
//询问
//从word.Length>0的word中选择word
//也没有选择(请尝试查看
//表达式树…选择已删除)
//投影如果不存在,则为隐式投影
//整个物体。
var query=从word到words
选择单词;
var exp=query.Expression;
var methodCallExpression=exp作为methodCallExpression;
if(methodCallExpression!=null)
{
MethodInfo方法=methodCallExpression.method;
if(method.DeclaringType==typeof(Queryable)&&method.Name==Select)
{
var source=methodCallExpression.Arguments[0];
var selector=methodCallExpression.Arguments[1];
//传递给Select的选择器参数是
//Expression.Quote(子表达式),
//其中,子表达式是lambda表达式
//word=>word在这里
if(selector.NodeType!=ExpressionType.Quote)
{
抛出新的NotSupportedException();
}
一元表达式一元=(一元表达式)选择器;
表达式操作数=一元操作数;
if(operand.NodeType!=ExpressionType.Lambda)
{
抛出新的NotSupportedException();
}
LambdaExpression lambda=(LambdaExpression)操作数;
//这是返回结果的“东西”
表达式body=lambda.body;
}
}
结尾处的
主体
应该是您想要的(或者可能是结尾前的lambda
)。请注意代码块开头的注释。使用您的方法,那么body
在我的代码中是thing.id==1
,而不是我希望的“单词”投影。@IngeHenriksen我只是在添加注释。。。查询来自word in words,其中word.Length>0 select word
也没有select(因此您的显然没有)。。。如果您使用函数表示法,那么原因就很清楚了:query.Where(word=>word.Length>0)
这里的选择在哪里?没有@英格恩里克森是的。。。但问题是你不清楚你想要得到什么。。。例如:query.Select(x=>new{Foo=x}).Where(x=>x.Foo.id==1).Select(x=>new{Bar=x.Foo}
这里有两个投影…你想要得到的就是complex@IngeHenriksenquery.Select(x=>new{Foo=x})。其中(x=>x.Foo.id==1)
这里的Select
是“隐藏的”在Where
后面,我看到了method.Name==“Where”
。我如何“取消隐藏”选择?