C# 如何编写Linq表达式?ie Func<;Exp<;Func<;十、 Y>>;,Exp<;Func<;Y、 Z>>;,Exp<;Func<;十、 Z>&燃气轮机&燃气轮机;
我正在创建一个C# 如何编写Linq表达式?ie Func<;Exp<;Func<;十、 Y>>;,Exp<;Func<;Y、 Z>>;,Exp<;Func<;十、 Z>&燃气轮机&燃气轮机;,c#,.net,linq,linq-expressions,C#,.net,Linq,Linq Expressions,我正在创建一个验证程序类。我正在尝试实现LinqSelectMany扩展方法,以便我的验证器能够使用Linq查询组合表达式,并在基础值更改时验证最终结果 下面的测试代码演示了我的意图 var a = 2; var b = 3; var va = Validator.Create(() => a, n => n >= 0 && n < 5); var vb = Validator.Create(() => b, n => n >= 0 &
验证程序类。我正在尝试实现LinqSelectMany
扩展方法,以便我的验证器能够使用Linq查询组合表达式,并在基础值更改时验证最终结果
下面的测试代码演示了我的意图
var a = 2;
var b = 3;
var va = Validator.Create(() => a, n => n >= 0 && n < 5);
var vb = Validator.Create(() => b, n => n >= 0 && n < 5);
var vc = from ia in va
from ib in vb
select ia + ib;
Debug.Assert(vc.Value == a + b); //2 + 3
Debug.Assert(vc.Value == 5);
Debug.Assert(vc.IsValid == true);
a = 7;
Debug.Assert(vc.Value == a + b); //7 + 3
Debug.Assert(vc.Value == 10);
Debug.Assert(va.IsValid == false);
Debug.Assert(vb.IsValid == true);
Debug.Assert(vc.IsValid == false);
我希望创建一个新表达式,如下所示:
public Expression<Func<bool>> IsValidExpression
{
get
{
// TODO: Compose expressions rather than compile & invoke.
}
}
提前谢谢 Haskell函数复合算子的等价性
在C#中可能是这样的吗
static Expression<Func<A, C>> Compose<A, B, C>(
Expression<Func<B, C>> f,
Expression<Func<A, B>> g)
{
var x = Expression.Parameter(typeof(A));
return Expression.Lambda<Func<A, C>>(
Expression.Invoke(f, Expression.Invoke(g, x)), x);
}
静态表达式组合(
表达式f,
表达式g)
{
var x=表达式参数(typeof(A));
返回表达式.Lambda(
Expression.Invoke(f,Expression.Invoke(g,x)),x);
}
这就是你要找的吗
例如:
Compose<int, int, string>(y => y.ToString(), x => x + 1).Compile()(10); // "11"
Compose(y=>y.ToString(),x=>x+1.Compile()(10);//"11"
虽然answer适用于多种场景,但它并不理想,因为这样的表达式不能在实体框架中使用,因为它不能处理调用调用。不幸的是,要避免这些调用,需要更多的代码,包括新的ExpressionVisitor
派生类:
static Expression<Func<A, C>> Compose<A, B, C>(Expression<Func<B, C>> f,
Expression<Func<A, B>> g)
{
var ex = ReplaceExpressions(f.Body, f.Parameters[0], g.Body);
return Expression.Lambda<Func<A, C>>(ex, g.Parameters[0]);
}
static TExpr ReplaceExpressions<TExpr>(TExpr expression,
Expression orig,
Expression replacement)
where TExpr : Expression
{
var replacer = new ExpressionReplacer(orig, replacement);
return replacer.VisitAndConvert(expression, nameof(ReplaceExpressions));
}
private class ExpressionReplacer : ExpressionVisitor
{
private readonly Expression From;
private readonly Expression To;
public ExpressionReplacer(Expression from, Expression to)
{
From = from;
To = to;
}
public override Expression Visit(Expression node)
{
return node == From ? To : base.Visit(node);
}
}
静态表达式组合(表达式f,
表达式g)
{
var ex=替换表达式(f.Body,f.Parameters[0],g.Body);
返回表达式.Lambda(例如,g.Parameters[0]);
}
静态TExpr表达式(TExpr表达式,
表达来源:,
表达式替换)
式中:表达式
{
var replacer=新表达式replacer(原始,替换);
返回replacer.VisitAndConvert(表达式,nameof(ReplaceExpressions));
}
私有类ExpressionReplacer:ExpressionVisitor
{
来自的私有只读表达式;
私有只读表达式;
public ExpressionReplacer(表达式from、表达式to)
{
From=From;
To=To;
}
公共重写表达式访问(表达式节点)
{
返回节点==从?到:基本访问(节点);
}
}
这将用第二个表达式中的表达式替换第一个表达式中第一个参数的每个实例。这样的电话:
public Expression<Func<bool>> IsValidExpression
{
get
{
// TODO: Compose expressions rather than compile & invoke.
}
}
Compose((Class1C)=>c.StringProperty,(Class2C2)=>c2.ClassProperty
将产生表达式(Class2 c2)=>c2.classproperty.StringProperty
,很难理解“以更功能化的方式”是什么意思。如果只删除所有的表达式.Compile()和.Invoke(),您还需要做些什么s?我很好奇为什么你想要验证一个表达式来产生值,而不是简单地验证一个实际值。你能详细说明这一点吗?这里有一个例子-我试图组合函数,比如f(x)=x+1&g(x)=sqrt(x),然后h(x)=f(g(x))。现在如果我对g有一个约束,使得x>=0然后,我希望这个约束传播到函数H。当X的基本值改变时,我想能够询问函数H,如果我认为它的结果仍然有效。(这是一个有点虚构的例子,但它应该有助于澄清。)干杯。我想这个堆栈交换可能会引起你的兴趣。如果它是你的支持,并帮助它进入测试版。这看起来很像我所追求的。干杯。现在我可以继续我的下一个头痛。Monads是疯狂的!我们的内部库中有一整套这样的操作符。很遗憾微软没有包含用于制作前任的东西pression真是太棒了(相对而言),作为旁注,只有当“f”和“g”是纯函数时,它才有效。如果你在实体框架中使用它,很可能它们已经是了。否则,你可能会遇到副作用问题。
(.) :: (b->c) -> (a->b) -> (a->c)
f . g = \ x -> f (g x)
static Expression<Func<A, C>> Compose<A, B, C>(
Expression<Func<B, C>> f,
Expression<Func<A, B>> g)
{
var x = Expression.Parameter(typeof(A));
return Expression.Lambda<Func<A, C>>(
Expression.Invoke(f, Expression.Invoke(g, x)), x);
}
Compose<int, int, string>(y => y.ToString(), x => x + 1).Compile()(10); // "11"
static Expression<Func<A, C>> Compose<A, B, C>(Expression<Func<B, C>> f,
Expression<Func<A, B>> g)
{
var ex = ReplaceExpressions(f.Body, f.Parameters[0], g.Body);
return Expression.Lambda<Func<A, C>>(ex, g.Parameters[0]);
}
static TExpr ReplaceExpressions<TExpr>(TExpr expression,
Expression orig,
Expression replacement)
where TExpr : Expression
{
var replacer = new ExpressionReplacer(orig, replacement);
return replacer.VisitAndConvert(expression, nameof(ReplaceExpressions));
}
private class ExpressionReplacer : ExpressionVisitor
{
private readonly Expression From;
private readonly Expression To;
public ExpressionReplacer(Expression from, Expression to)
{
From = from;
To = to;
}
public override Expression Visit(Expression node)
{
return node == From ? To : base.Visit(node);
}
}