gpt4 book ai didi

c# - 重写表达式以用自定义方法替换 List.Contains

转载 作者:太空狗 更新时间:2023-10-30 01:20:49 25 4
gpt4 key购买 nike

为了扩大我的技能组合,我正在尝试学习如何重写表达式。

目标:给定一个表达式,我想替换 List.Contains() 的实例调用我自己的静态方法 InList .例如,下面两个表达式应该是等价的:

Expression<Func<Foo,bool>> expr1 = myRewriter.Rewrite(foo => fooList.Contains(foo));
Expression<Func<Foo,bool>> expr2 = foo => InList(foo, fooList);

我的尝试:我了解到使用 custom ExpressionVisitor是基于现有表达式创建新表达式的最佳方式。但是,我无法构建新的 MethodCallExpression这实际上调用了我的方法。这是我尝试过的:

public class InListRewriter<T> : ExpressionVisitor
{
public static bool InList(T target, List<T> source)
{
// this is my target method
return true;
}

public Expression<Func<T, bool>> Rewrite(Expression<Func<T, bool>> expression)
{
return Visit(expression) as Expression<Func<T,bool>>;
}

protected override Expression VisitMethodCall(MethodCallExpression node)
{
// Only rewrite List.Contains()
if (!node.Method.Name.Equals("Contains", StringComparison.InvariantCultureIgnoreCase))
return base.VisitMethodCall(node);

// Extract parameters from original expression
var sourceList = node.Object; // The list being searched
var target = node.Method.GetParameters()[0]; // The thing being searched for

// Create new expression
var type = typeof (InListRewriter<T>);
var methodName = "InList";
var typeArguments = new Type[] { };
var arguments = new[] { Expression.Parameter(target.ParameterType, target.Name), sourceList };
var newExpression = Expression.Call(type, methodName, typeArguments, arguments);

return newExpression;
}
}

但是,当我通过 new InListRewriter<Foo>().Rewrite(foo => fooList.Contains(foo)) 调用它时,我得到一个 InvalidOperationExceptionExpression.Call期间:

No method 'InList' on type 'MyNamespace.InListRewriter`1[MyNamespace.Foo]' is compatible with the supplied arguments.

我什至尝试制作一个具有极其通用签名的新 InList:

public static bool InList(params object[] things) {...}

但是还是报同样的错误。我究竟做错了什么?我想做的事有可能吗?

最佳答案

您的代码有一个大问题:它传递的参数不正确,特别是第一个。

您需要使用实际参数而不是 Expression.Parameter(target.ParameterType, target.Name):node.Arguments[0]

此外,我建议您使用 Expression.Call 的不同重载:采用 MethodInfo 的重载。

最终代码如下所示:

protected override Expression VisitMethodCall(MethodCallExpression node)
{
// Only rewrite List.Contains()
if (!node.Method.Name.Equals("Contains",
StringComparison.InvariantCultureIgnoreCase))
return base.VisitMethodCall(node);

// Extract parameters from original expression
var sourceList = node.Object; // The list being searched
var target = node.Arguments[0]; // The thing being searched for
var newMethod = GetType().GetMethod("InList",
BindingFlags.Static | BindingFlags.Public);

// Create new expression
var newExpression = Expression.Call(newMethod, target, sourceList);

return newExpression;
}

关于c# - 重写表达式以用自定义方法替换 List.Contains,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17728188/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com