2016-07-20 14 views
1

Ich versuche, einige zusätzliche Funktion für eine Regel-Engine zu bauen, das ich arbeite Expression Bäume auf verwendet, die auf diesen Beitrag basiert - How to implement a rule engine?Return Standarddatetime mit Linq Expression

Eine der Regeln, die ich habe Hinzufügen von Minuten zu einer Eigenschaft, wenn dieser Eigenschaftstyp als DateTime gefunden wird. So könnte ich zum Beispiel "DOB + 60" oder "DOB - 180" haben.

Mein aktueller Code arbeitet dafür:

var expression = new string[] {"DOB", "+", "60"}; 

var property = Expression.Property(param, expression[0]); 
var method = typeof(T).GetProperty(expression[0]).PropertyType.GetMethod("AddMinutes"); 

/* If we have a AddMinutes method then assume type is of DateTime */ 
if (method != null) 
{ 
    var tParam = method.GetParameters()[0].ParameterType; 

    /* Calculate if we're adding or subtracting minutes */ 
    var convertedNo = expression[1] == "-" ? int.Parse(expression[2]) * -1 : int.Parse(expression[2]); 

     var number = Expression.Constant(Convert.ChangeType(convertedNo, tParam)); 
     var exp = Expression.Call(property, method, number); 

     /* Allows for left property < DOB.AddMinutes(60) */ 
     return Expression.MakeBinary(ExpressionType.LessThan, left, exp); 
} 

Das Problem das ich habe, ist, dass die DOB Eigenschaft kann auf DateTime.Min so eingestellt werden, dass, wenn mein Ausdruck kommt zu bewerten „DOB - 180“ In diesem Fall wird eine Out of Bounds-Ausnahme ausgelöst, wenn versucht wird, 180 Minuten von DateTime.Min abzuziehen.

Ich versuchte, um dieses Problem zu umgehen, indem Sie eine Expression.IfThenElse verwenden, so dass, wenn die DateTime-Eigenschaft gleich DateTime.Min ist, die Berechnung nicht und nur auf DateTime.Min ausgewertet werden.

Meine aktualisierten Code sieht wie folgt aus:

var expression = new string[] {"DOB", "-", "180"}; 

var property = Expression.Property(param, expression[0]); 
var method = typeof(T).GetProperty(expression[0]).PropertyType.GetMethod("AddMinutes"); 

/* If we have a AddMinutes method then assume type is of DateTime */ 
if (method != null) 
{ 
    var tParam = method.GetParameters()[0].ParameterType; 

    /* Calculate if we're adding or subtracting minutes */ 
    var convertedNo = expression[1] == "-" ? int.Parse(expression[2]) * -1 : int.Parse(expression[2]); 

     var number = Expression.Constant(Convert.ChangeType(convertedNo, tParam)); 
     var exp = Expression.Call(property, method, number); 

     var minDate = Expression.Constant(Convert.ChangeType(DateTime.MinValue, typeof(DateTime))); 
     var minDateCheck = Expression.MakeBinary(ExpressionType.Equal, property, minDate); 

     var minDateExp = Expression.IfThenElse(minDateCheck, minDate, exp); 

     /* To allow for left property < DOB == DateTime.Min ? DateTime.Min : DOB.AddMinutes(60) */ 
     return Expression.MakeBinary(ExpressionType.LessThan, left, minDateExp); // Exception thrown here 
} 

Leider wirft dies die Ausnahme - Kann nicht mit Datetime-Typ void Rückkehr vergleichen. Ich habe verschiedene Varianten ausprobiert, aber immer die gleiche Ausnahme.

Wäre jemand in der Lage, mir zu zeigen, wie ich einen Ausdruck konstruieren könnte, der diese Logik tun könnte?

+0

Situationen wie diese mache ich in einem Testprogramm do 'Expression > test = (x) => x

+0

Lustigerweise war es einer meiner Tests, der das Problem erwischte! Danke für den Tipp, ich werde es in Zukunft versuchen. – QTheIntro

Antwort

3

Expression.IfThenElse entspricht der C# - na ja, if Aussage, während das, was Sie brauchen, ist der Ausdruck Äquivalent des C# ?: (a.k.a bedingte) Operator, der ConditionalExpression und wird von Expression.Condition Verfahren hergestellt.

Kurz, ersetzen

var minDateExp = Expression.IfThenElse(minDateCheck, minDate, exp); 

mit

var minDateExp = Expression.Condition(minDateCheck, minDate, exp); 

und Sie sind fertig.

+0

Perfekt, arbeitete eine Belohnung - ich hatte gehofft, es war etwas einfaches, das ich vermisst hatte. Ich schätze die Hilfe und die Erklärung - es ist gut, für andere Ausdrücke zu wissen, die ich aufbauen werde. Danke noch einmal. – QTheIntro

Verwandte Themen