我正在尝试函数式编程及其各种概念.所有这些都非常有趣.我曾几次读过Currying以及它有什么优势.
但我不明白这一点.以下来源演示了咖喱概念的使用和linq的解决方案.实际上,我没有看到任何使用currying概念的建议.
那么,使用currying有什么好处?
static bool IsPrime(int value)
{
int max = (value / 2) + 1;
for (int i = 2; i < max; i++)
{
if ((value % i) == 0)
{
return false;
}
}
return true;
}
static readonly Func<IEnumerable<int>, IEnumerable<int>> GetPrimes =
HigherOrder.GetFilter<int>().Curry()(IsPrime);
static void Main(string[] args)
{
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
Console.Write("Primes:");
//Curry
foreach (int n in GetPrimes(numbers))
{ …Run Code Online (Sandbox Code Playgroud) 我正在为我们系统的一部分编写数据层,该数据层记录有关每天运行的自动作业的信息 - 作业名称,运行时间,结果,等等.
我正在使用Entity Framework与数据库交谈,但我试图将这些细节隐藏在更高级别的模块之外,我不希望实体对象本身被暴露.
但是,我想使我的界面在用于查找作业信息的标准中非常灵活.例如,用户界面应允许用户执行复杂的查询,例如"给我所有名为'hello'的作业,该作业在上午10:00到11:00之间运行失败." 显然,这看起来像是动态构建Expression树的工作.
所以我希望我的数据层(存储库)能够接受类型Expression<Func<string, DateTime, ResultCode, long, bool>>(lambda表达式)的LINQ表达式,然后在后台将该lambda转换为我的实体框架ObjectContext可以用作Where()子句中的过滤器的表达式.
简而言之,我正在尝试将类型的lambda表达式转换Expression<Func<string, DateTime, ResultCode, long, bool>>为Expression<Func<svc_JobAudit, bool>>,其中svc_JobAuditEntity Framework数据对象对应于存储作业信息的表.(第一个委托中的四个参数分别对应于作业名称,运行时间,结果以及分别在MS中花费的时间)
我在使用该ExpressionVisitor课程时取得了很好的进展,直到我碰到了一堵砖墙并收到了一条InvalidOperationException错误消息:
从"VisitLambda"调用时,重写"System.Linq.Expressions.ParameterExpression"类型的节点必须返回相同类型的非null值.或者,覆盖"VisitLambda"并将其更改为不访问此类型的子项.
我完全不知所措.为什么它不允许我将引用参数的表达式节点转换为引用属性的节点?还有另一种方法可以解决这个问题吗?
以下是一些示例代码:
namespace ExpressionTest
{
class Program
{
static void Main(string[] args)
{
Expression<Func<string, DateTime, ResultCode, long, bool>> expression = (myString, myDateTime, myResultCode, myTimeSpan) => myResultCode == ResultCode.Failed && myString == "hello";
var result = ConvertExpression(expression);
}
private static Expression<Func<svc_JobAudit, bool>> …Run Code Online (Sandbox Code Playgroud) 考虑这段代码:
public class Foo
{
public int a { get; set; }
public int b { get; set; }
}
private void Test()
{
List<Foo> foos = new List<Foo>();
foos.Add(new Foo());
foos.Add(new Foo());
Expression<Func<Foo, int>> exp0 = f => f.a * f.b;
Expression<Func<int>> exp1 = () => foos[0].a * foos[0].b;
Expression<Func<int>> exp2 = () => foos[1].a * foos[1].b;
}
Run Code Online (Sandbox Code Playgroud)
你怎么能把exp0它变成两个与exp1和相同的表达式exp2.请注意,我不想仅为exp0每个Fooin 评估foos,而是获得两个新表达式.
[更新]:
基本上,我希望能够扩大或"扁平化"传递给A的表达Linq扩展方法,如Sum入枚举每个项目一个表达,因为这些枚举是静态的,因为我已经有代码读取不表达获取参数(然后将它们转换为另一种语言). …
我正在尝试构建一个表达式树,我可以将它输入到 Linq2SQL 中,以便它生成一个漂亮的干净查询。我的目的是构建一个过滤器,将任意一组单词与 AND 和 NOT(或 OR 和 NOT)放在一起。因为我想改变我搜索的字段,所以我最好Expresssion<Func<T, string, bool>>通过调用各种辅助函数来组合一个's列表(其中 T 是我正在操作的实体)。然后我会收到一组单词并循环遍历它们并构建一个Expresssion<Func<T, bool>>up(在必要时否定某些表达式),我最终可以将其提供给 .Where 语句。
我一直在使用 LINQKit PredicateBuilder但这段代码处理单参数表达式。然而,它为我自己的尝试提供了一些基础。我的目标是做这样的事情:
var e = (Expression<Func<Entity, string, bool>>)((p, w) => p.SomeField.ToLower().Contains(w));
var words = new []{"amanda", "bob"};
var expr = (Expression<Func<Entity, bool>>)(p => false);
// building up an OR query
foreach(var w in words) {
var w1 = w;
>>>>expr = Expression.Lambda<Func<Entity, bool>>(Expression.OrElse(expr.Body, (Expression<Func<Entity, bool>>)(p => e(p, w))));
}
var filteredEntities = table.Where(expr);
Run Code Online (Sandbox Code Playgroud)
但是由于我使用的是表达式,所以用 >>>> 标记的行显然是非法的(不能e(p, w) …