private Expression create(DecisionNode node)
{
if (!node.IsLeaf)
{
int attributeIndex = node.Branches.AttributeIndex;
// Create all comparison expressions
BinaryExpression[] comparisons = new BinaryExpression[node.Branches.Count];
Expression[] childExpression = new Expression[node.Branches.Count];
for (int i = 0; i < comparisons.Length; i++)
{
DecisionNode child = node.Branches[i];
var expr = Expression.ArrayIndex(inputs, Expression.Constant(attributeIndex));
var cons = Expression.Constant(child.Value);
switch (child.Comparison)
{
case ComparisonKind.Equal:
comparisons[i] = Expression.Equal(expr, cons); break;
case ComparisonKind.GreaterThan:
comparisons[i] = Expression.GreaterThan(expr, cons); break;
case ComparisonKind.GreaterThanOrEqual:
comparisons[i] = Expression.GreaterThanOrEqual(expr, cons); break;
case ComparisonKind.LessThan:
comparisons[i] = Expression.LessThan(expr, cons); break;
case ComparisonKind.LessThanOrEqual:
comparisons[i] = Expression.LessThanOrEqual(expr, cons); break;
case ComparisonKind.NotEqual:
comparisons[i] = Expression.NotEqual(expr, cons); break;
default:
throw new InvalidOperationException("Unexpected node comparison type.");
}
childExpression[i] = create(node.Branches[i]);
}
// Create expression for else expressions
ConstructorInfo ex = typeof(ArgumentException).GetConstructor(new[] { typeof(string), typeof(string) });
var lastElse = Expression.IfThenElse(comparisons[comparisons.Length - 1],
childExpression[comparisons.Length - 1],
Expression.Throw(Expression.New(ex,
Expression.Constant("Input contains a value outside of expected ranges."),
Expression.Constant("input"))));
ConditionalExpression currentIf = null;
for (int i = comparisons.Length - 2; i >= 0; i--)
{
currentIf = Expression.IfThenElse(comparisons[i],
childExpression[i], lastElse);
lastElse = currentIf;
}
return currentIf;
}
else // node is a leaf
{
if (node.Output.HasValue)
return Expression.Return(label, Expression.Constant(node.Output.Value), typeof(int));
return Expression.Return(label, Expression.Constant(-1), typeof(int));
}
}