我该如何撰写Linq的前pressions?即Func键<精通<函数功能:其中,X,Y>>中精通< Func键< Y,Z>>中精通< Func键&

由网友(喂、不爱就让开点)分享简介:我创建一个验证器; T> 类。我试图实现的LINQ我的验证,以便能够即使构成使用LINQ查询EX pressions和验证的最终结果的根本的SelectMany 扩展方法值的变化。I'm creating a Validator class. I'm attempting to implement the...

我创建一个验证器; T> 类。我试图实现的LINQ我的验证,以便能够即使构成使用LINQ查询EX pressions和验证的最终结果的根本的SelectMany 扩展方法值的变化。

I'm creating a Validator<T> class. I'm attempting to implement the Linq SelectMany extension methods for my validator to be able to compose expressions using a Linq query and validate the final result even when the underlying values change.

下面的测试code说明我的意图。

The following test code demonstrates my intent.

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);

我已经看到了以下问题怎样撰写现有的LINQ防爆pressions 这说明我如何组合两个 Func键&LT; T,布尔&GT; 的一起使用 EX pression,但我需要能够撰写功能一起更,好,实用的方式。

I've seen the following question How do I compose existing Linq Expressions which shows me how to compose two Func<T, bool>'s together using an And expression, but I need to be able to compose functions together in a more, well, functional way.

我有,例如,下面的两个前pressions:

I have, for example, the following two expressions:

public Expression<Func<T>> ValueExpression { get; private set; }
public Expression<Func<T, bool>> ValidationExpression { get; private set; }

我想创建一个新的EX pression是这样的:

I wish to create a new expression like this:

    public Expression<Func<bool>> IsValidExpression
    {
        get
        {
            // TODO: Compose expressions rather than compile & invoke.
        }
    }

更简洁地说我试图创建这些功能:

More succinctly I'm trying to create these functions:

// Specific case
Func<Expression<Func<T>>, Expression<Func<T, bool>>, Expression<Func<bool>>>
// General case
Func<Expression<Func<X, Y>>, Expression<Func<Y, Z>>, Expression<Func<X, Z>>>

一般情况下,功能可以被修改以接受不同数量的通用参数按需要来撰写任何功能。

The general case function can be modified to accept different numbers of generic arguments as needed to compose any function.

我搜索堆栈溢出(当然)和网络,但都没有能够解决这个问题的一个例子。

I've searched Stack Overflow (of course) and the web, but haven't an example that solves this issue.

我的code为验证器; T&GT; 类是低​​于

My code for the Validator<T> class is below.

public class Validator<T>
{
    public Validator(Expression<Func<T>> valueFunc,
        Expression<Func<T, bool>> validationFunc)
    {
        this.ValueExpression = valueFunc;
        this.ValidationExpression = validationFunc;
    }

    public Expression<Func<T>> ValueExpression { get; private set; }
    public Expression<Func<T, bool>> ValidationExpression { get; private set; }

    public T Value { get { return this.ValueExpression.Compile().Invoke(); } }

    public bool IsValid { get { return this.IsValidExpression.Compile().Invoke(); } }

    public Expression<Func<bool>> IsValidExpression
    {
        get
        {
            // TODO: Compose expressions.
        }
    }
}

我的的SelectMany 扩展包含负载令人讨厌 .Compile()调用(),我想摆脱的。

My SelectMany extensions contain loads of yucky .Compile().Invoke() which I want to get rid of.

public static Validator<U> SelectMany<T, U>(this Validator<T> @this, Expression<Func<T, Validator<U>>> k)
{
    Expression<Func<T>> fvtv = @this.ValueExpression;
    Expression<Func<Validator<U>>> fvu = () => k.Compile().Invoke(fvtv.Compile().Invoke());
    Expression<Func<U>> fvuv = fvu.Compile().Invoke().ValueExpression;
    Expression<Func<U, bool>> fvtiv = u => @this.ValidationExpression.Compile().Invoke(fvtv.Compile().Invoke());
    return fvuv.ToValidator(fvtiv);
}

public static Validator<V> SelectMany<T, U, V>(this Validator<T> @this, Expression<Func<T, Validator<U>>> k, Expression<Func<T, U, V>> s)
{
    Expression<Func<Validator<U>>> fvu = () => @this.SelectMany(k);
    Expression<Func<T>> fvtv = @this.ValueExpression;
    Expression<Func<U>> fvuv = fvu.Compile().Invoke().ValueExpression;
    Expression<Func<T, bool>> fvtiv = @this.ValidationExpression;
    Expression<Func<U, bool>> fvuiv = u => fvu.Compile().Invoke().ValidationExpression.Compile().Invoke(u);
    Expression<Func<V>> fvv = () => s.Compile().Invoke(fvtv.Compile().Invoke(), fvuv.Compile().Invoke());
    Expression<Func<V, bool>> fvviv = v => fvtiv.Compile().Invoke(fvtv.Compile().Invoke()) && fvuiv.Compile().Invoke(fvuv.Compile().Invoke());
    return fvv.ToValidator(fvviv);
}

在此先感谢!

Thanks in advance!

推荐答案

Haskell的函数组合的操作符

The equivalent of Haskell's function composition operator

(.) :: (b->c) -> (a->b) -> (a->c)
f . g =  x -> f (g x)

将在C#中可能会像

would in C# probably be something like

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);
}

这是你要找的是什么?

Is this what you're looking for?

例如:

Compose<int, int, string>(y => y.ToString(), x => x + 1).Compile()(10); // "11"
阅读全文

相关推荐

最新文章