使用 LinqKit 构建的 c# Lambda 表达式无法编译
这个 lambda 无法编译,但我不明白为什么。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using LinqKit;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
var barModel = new BarModel();
string id = "some";
Console.WriteLine(barModel.subFor(id).ToString());
// output: m => (True AndAlso (m.key == value(ConsoleApplication2.Bar`1+<>c__DisplayClass0[ConsoleApplication2.Model]).id))
Console.ReadKey();
var subworkitems = barModel.list.Where(barModel.subFor(id).Compile());
// Exception {"variable 'm' of type 'ConsoleApplication2.Model' referenced from scope '', but it is not defined"}
Console.WriteLine(subworkitems.ToString());
Console.ReadKey();
}
}
class Bar<TModel>
{
public Bar(Expression<Func<TModel, string>> foreignKeyExpression)
{
_foreignKeyExpression = foreignKeyExpression;
}
private Expression<Func<TModel, string>> _foreignKeyExpression { get; set; }
public Expression<Func<TModel, bool>> subFor(string id)
{
var ex = forTargetId(id);
return ex;
}
public Expression<Func<TModel, bool>> forTargetId(String id)
{
var fc = _foreignKeyExpression;
Expression<Func<TModel, bool>> predicate = m => true;
var result = predicate.And(m => fc.Invoke(m) == id).Expand();
return result;
}
}
class Model
{
public string key;
public string value;
}
class BarModel : Bar<Model>
{
public List<Model> list;
public BarModel() : base(m => m.key)
{
list = new List<Model>();
}
}
}
This lambda does not compile, but I do not understand why.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using LinqKit;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
var barModel = new BarModel();
string id = "some";
Console.WriteLine(barModel.subFor(id).ToString());
// output: m => (True AndAlso (m.key == value(ConsoleApplication2.Bar`1+<>c__DisplayClass0[ConsoleApplication2.Model]).id))
Console.ReadKey();
var subworkitems = barModel.list.Where(barModel.subFor(id).Compile());
// Exception {"variable 'm' of type 'ConsoleApplication2.Model' referenced from scope '', but it is not defined"}
Console.WriteLine(subworkitems.ToString());
Console.ReadKey();
}
}
class Bar<TModel>
{
public Bar(Expression<Func<TModel, string>> foreignKeyExpression)
{
_foreignKeyExpression = foreignKeyExpression;
}
private Expression<Func<TModel, string>> _foreignKeyExpression { get; set; }
public Expression<Func<TModel, bool>> subFor(string id)
{
var ex = forTargetId(id);
return ex;
}
public Expression<Func<TModel, bool>> forTargetId(String id)
{
var fc = _foreignKeyExpression;
Expression<Func<TModel, bool>> predicate = m => true;
var result = predicate.And(m => fc.Invoke(m) == id).Expand();
return result;
}
}
class Model
{
public string key;
public string value;
}
class BarModel : Bar<Model>
{
public List<Model> list;
public BarModel() : base(m => m.key)
{
list = new List<Model>();
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
解决方案 1
此解决方案不会删除调用语句,我假设您尝试通过调用“Expand”来执行此操作。
将“forTargetId(String id)”的结果更改为
当表达式在 where 子句中编译时,它会知道需要将“m”传递给上面的 fc 表达式。
,我的第一个提示出现了
当我更改为时
,我可以看到 n 根本没有被传递。
我通过如下操作 Main 方法测试了此更改。
解决方案 2
此解决方案确实使用 Expand 方法删除了 Invoke 语句,但更改了将语句连接在一起的方式。
LinqKit 网站上对“Expand”功能的宣传如下。
请注意,他们没有使用“And”方法将这些内容放在一起,而是将调用“菊花链”在一起。
而不是
这样做
Solution 1
This solution doesn't strip out the invoke statements which I assume you are trying to do by calling "Expand".
change the result of "forTargetId(String id)" to
When the expression is compiled in the where clause it will know that it needs to pass "m" to the fc expression above.
My first tip came when I changed
to
and I could see that n was not being pass along at all.
I tested out this change by manipulating the Main method as follows
Solution 2
This solution does remove the Invoke statements with the use of the Expand method but changes the way that you are anding the statements together.
The "Expand" function is advertised as following on the LinqKit website.
Notice that they aren't using the "And" method to put these things together but instead they are "daisy chaining" the calls together.
Instead of
Do this