Ich erstelle eine Validator<T>
Klasse. Ich versuche, die Linq Erweiterungs-Methoden für meine Validator zu implementieren, in der Lage, Ausdrücke mit einer Linq-Abfrage zu erstellen und das Endergebnis zu überprüfen, selbst wenn die zugrunde liegenden Werte ändern.Wie komponiere ich Linq Expressions? dh Func <Exp <Func<X, Y>>, Exp <Func<Y, Z>>, Exp <Func<X, Z> >>
Der folgende Testcode zeigt meine Absicht.
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);
Ich habe die folgende Frage How do I compose existing Linq Expressions gesehen, die zeigt mir, wie zwei Func<T, bool>
‚s komponieren zusammen einen And
Ausdruck, aber ich muß in der Lage sein, Funktionen zu komponieren zusammen in einem, nun ja, funktional.
Ich habe zum Beispiel die beiden folgenden Ausdrücke:
public Expression<Func<T>> ValueExpression { get; private set; }
public Expression<Func<T, bool>> ValidationExpression { get; private set; }
Ich möchte einen neuen Ausdruck wie folgt erstellen:
public Expression<Func<bool>> IsValidExpression
{
get
{
// TODO: Compose expressions rather than compile & invoke.
}
}
kurz und bündig diese Funktionen erstellen Ich versuche:
// 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>>>
Die allgemeine Fallfunktion kann geändert werden, um verschiedene Nummern von generischem Argumen zu akzeptieren ts wie benötigt, um eine Funktion zu komponieren.
Ich habe Stack Overflow (natürlich) und das Web gesucht, aber kein Beispiel, das dieses Problem löst.
Mein Code für die Klasse Validator<T>
ist unten.
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.
}
}
}
Meine SelectMany
Erweiterungen enthalten Lasten von ekligen .Compile().Invoke()
, die ich loswerden will.
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);
}
Vielen Dank im Voraus!
Wirklich kämpfen, um zu sehen, was Sie "auf eine funktionellere Weise" bedeuten. Was würden Sie tun müssen, dass Sie nicht alle Expression <>. – pdr
Ich bin neugierig, warum Sie einen * Ausdruck validieren sollten, um den Wert * zu erzeugen, anstatt einfach einen * tatsächlichen Wert * zu validieren. Können Sie diesen Punkt näher ausführen? – Aaronaught
Hier ist ein Beispiel - ich versuche Funktionen wie f (x) = x + 1 & g (x) = sqrt (x) dann h (x) = f (g (x)) zu komponieren. Nun, wenn ich eine Einschränkung für g habe, so dass x> = 0 (sqrt von -ve-Zahlen usw.), dann möchte ich, dass diese Beschränkung sich auf die Funktion h ausbreitet. Wenn sich mein zugrunde liegender Wert von x ändert, möchte ich die Funktion h fragen können, wenn ich das Ergebnis als noch gültig betrachten sollte. (Dies ist ein etwas künstliches Beispiel, aber es sollte helfen, zu klären.) Prost. – Enigmativity