public abstract class ExpressionNode
{
public abstract dynamic Evaluate();
public virtual void HandleObject( object obj)
{
}
public abstract IEnumerable <ExpressionNode> GetChildren();
}
* This source code was highlighted with Source Code Highlighter .
public class Constant : ExpressionNode
{
private readonly dynamic _value;
public Constant(dynamic value )
{
_value = value ;
}
public override dynamic Evaluate()
{
return _value;
}
public override IEnumerable <ExpressionNode> GetChildren()
{
yield break ;
}
}
* This source code was highlighted with Source Code Highlighter .
public class ObjectProperty : ExpressionNode
{
private dynamic _value = null ;
private readonly string _name;
private bool _propertyNotFound;
public ObjectProperty( string name)
{
_name = name;
}
public override void HandleObject( object obj)
{
try
{
_value = obj.GetType().GetProperty(_name).GetValue(obj, new object [0]);
}
catch (Exception ex)
{
_propertyNotFound = true ;
_value = null ;
}
}
public override dynamic Evaluate()
{
if (_propertyNotFound)
{
throw new PropertyNotFoundException();
}
return _value;
}
public override IEnumerable <ExpressionNode> GetChildren()
{
yield break ;
}
}
* This source code was highlighted with Source Code Highlighter .
public class HasPropertyChecker : ExpressionNode
{
private readonly string _name;
private bool _result;
public HasPropertyChecker( string name)
{
_name = name;
}
public override dynamic Evaluate()
{
return _result;
}
public override IEnumerable <ExpressionNode> GetChildren()
{
yield break ;
}
public override void HandleObject( object obj)
{
_result = obj.GetType().GetProperty(_name) != null ;
}
}
* This source code was highlighted with Source Code Highlighter .
public abstract class UnaryOperator : ExpressionNode
{
private readonly ExpressionNode _argument;
protected UnaryOperator(ExpressionNode arg)
{
_argument = arg;
}
protected abstract dynamic EvaluateUnary(dynamic arg);
public override dynamic Evaluate()
{
return EvaluateUnary(_argument.Evaluate());
}
public override IEnumerable <ExpressionNode> GetChildren()
{
yield return _argument;
}
}
* This source code was highlighted with Source Code Highlighter .
[Operator( "not" )]
public class Not : UnaryOperator
{
public Not( params ExpressionNode[] args) : this (args[0]) { Debug.Assert(args.Length == 1); }
public Not(ExpressionNode arg) : base (arg) { }
protected override dynamic EvaluateUnary(dynamic arg)
{
return !arg;
}
}
* This source code was highlighted with Source Code Highlighter .
public abstract class BinaryOperator : ExpressionNode
{
private readonly ExpressionNode _argument1;
private readonly ExpressionNode _argument2;
protected BinaryOperator(ExpressionNode arg1, ExpressionNode arg2)
{
_argument1 = arg1;
_argument2 = arg2;
}
protected abstract dynamic EvaluateBinary(dynamic arg1, dynamic arg2);
public override dynamic Evaluate()
{
return EvaluateBinary(_argument1.Evaluate(), _argument2.Evaluate());
}
public override IEnumerable <ExpressionNode> GetChildren()
{
yield return _argument1;
yield return _argument2;
}
}
[Operator( "add" )]
public class Add : BinaryOperator
{
public Add( params ExpressionNode[] args) : this (args[0], args[1]) { Debug.Assert(args.Length == 2); }
public Add(ExpressionNode arg1, ExpressionNode arg2) : base (arg1, arg2) { }
protected override dynamic EvaluateBinary(dynamic arg1, dynamic arg2)
{
return arg1 + arg2;
}
}
* This source code was highlighted with Source Code Highlighter .
public abstract class AgregateOperator : ExpressionNode
{
private readonly ExpressionNode[] _arguments;
protected AgregateOperator( params ExpressionNode[] args)
{
_arguments = args;
}
protected abstract dynamic EvaluateAgregate( IEnumerable <dynamic> args);
public override dynamic Evaluate()
{
return EvaluateAgregate(_arguments.ConvertAll(x => x.Evaluate()));
}
public override IEnumerable <ExpressionNode> GetChildren()
{
return _arguments;
}
}
[Operator( "and" )]
public class And : AgregateOperator
{
public And( params ExpressionNode[] args) : base (args) { }
protected override dynamic EvaluateAgregate( IEnumerable <dynamic> args)
{
foreach (dynamic arg in args)
{
if (!arg)
{
return arg;
}
}
return true ;
}
}
* This source code was highlighted with Source Code Highlighter .
public class BooleanExpressionTree
{
public BooleanExpressionTree(ExpressionNode root)
{
Root = root;
}
public ExpressionNode Root { get ; private set ; }
public bool EvaluateOnObject(dynamic obj)
{
lock ( this )
{
PrepareTree(obj, Root);
return ( bool )Root.Evaluate();
}
}
private void PrepareTree(dynamic obj, ExpressionNode node)
{
node.HandleObject(obj);
foreach (ExpressionNode child in node.GetChildren())
{
PrepareTree(obj, child);
}
}
}
* This source code was highlighted with Source Code Highlighter .
public class Human
{
public object Legs { get { return new object (); } }
public object Hands { get { return new object (); } }
public int LegsCount { get { return 2; } }
public int HandsCount { get { return 2; } }
public string Name { get ; set ; }
}
public class OldMan : Human
{
public DateTime BirthDate { get { return new DateTime (1933, 1, 1); } }
}
public class Baby : Human
{
public DateTime BirthDate { get { return new DateTime (2009, 1, 1); } }
}
public class Animal
{
public int LegsCount { get { return 4; } }
public object Tail { get { return new object (); } }
public string Name { get ; set ; }
}
public class Dog : Animal
{
public DateTime BirthDate { get ; set ; }
}
* This source code was highlighted with Source Code Highlighter .
static IEnumerable < object > PrepareTestObjects()
{
List < object > objects = new List < object >();
objects.Add( new Human { Name = "Some Stranger" });
objects.Add( new OldMan { Name = "Ivan Petrov" });
objects.Add( new OldMan { Name = "John Smith" });
objects.Add( new Baby { Name = "Vasya Pupkin" });
objects.Add( new Baby { Name = "Bart Simpson" });
objects.Add( new Dog { Name = "Sharik" , BirthDate = new DateTime (2004, 11, 11) });
objects.Add( new Dog { Name = "Old Zhuchka" , BirthDate = new DateTime (1900, 11, 11) });
return objects;
}
* This source code was highlighted with Source Code Highlighter .
IsHuman:
< and >
< has-property name ="Hands" />
< has-property name ="Legs" />
< not >
< has-property name ="Tail" />
</ not >
< equals >
< property name ="HandsCount" />
< constant value ="2" type ="int" />
</ equals >
< equals >
< property name ="LegsCount" />
< constant value ="2" type ="int" />
</ equals >
</ and >
IsNotAmerican:
< and >
< has-property name ="Name" />
< or >
< like >
< property name ="Name" />
< constant value ="Ivan" type ="string" />
</ like >
< like >
< property name ="Name" />
< constant value ="Vasya" type ="string" />
</ like >
</ or >
</ and >
IsOld:
< and >
< has-property name ="BirthDate" />
< gt >
< sub >
< constant value ="2009-12-23" type ="datetime" />
< property name ="BirthDate" />
</ sub >
< constant value ="22000.00:00:00" type ="timespan" />
</ gt >
</ and >
* This source code was highlighted with Source Code Highlighter .
Test Is Human:
Some Stranger - True
Ivan Petrov - True
John Smith - True
Vasya Pupkin - True
Bart Simpson - True
Sharik - False
Old Zhuchka - False
Test Is Old:
Some Stranger - False
Ivan Petrov - True
John Smith - True
Vasya Pupkin - False
Bart Simpson - False
Sharik - False
Old Zhuchka - True
Test Is Not American:
Some Stranger - False
Ivan Petrov - True
John Smith - False
Vasya Pupkin - True
Bart Simpson - False
Sharik - False
Old Zhuchka - False
Source: https://habr.com/ru/post/79258/
All Articles