// perhaps something like this // e.g. FormulaValueSource would have all the formulas //public ExecutionEngine AddValueSource(IValueSource valueSource) //{ //} public ExecutionContext Execute(Guid formulaId, IEnumerable <ArgumentValue> argumentValues, IContextLogger logger) { Guard.AgainstNull(argumentValues, nameof(argumentValues)); Guard.AgainstNull(logger, nameof(logger)); Initialize(); var context = new ExecutionContext(argumentValues, logger); foreach (var argumentValue in argumentValues) { var argument = GetArgument(argumentValue.Id); if (logger.LogLevel == ContextLogLevel.Verbose) { logger.LogVerbose($"[inputParameter] {argumentValue.Id} / {argument.Name} = '{argumentValue.Value}'"); } } try { Execute(context, formulaId, logger); } catch (Exception ex) { context.WithException(ex); } return(context); }
private FormulaContext Execute(ExecutionContext executionContext, Guid formulaId, IContextLogger logger) { var formula = GetFormula(formulaId); executionContext.CyclicInvariant(formula.Name); using (var formulaContext = executionContext.FormulaContext(formula.Name)) { foreach (var constraint in formula.Constraints) { var argument = GetArgument(constraint.ArgumentId); var argumentValue = executionContext.GetArgumentValue(constraint.ArgumentId); if (!_valueComparer.IsSatisfiedBy(argument.DataType, argumentValue, constraint.Comparison, constraint.Value)) { if (logger.LogLevel == ContextLogLevel.Verbose) { logger.LogVerbose($"[disqualified] {argument.Name} is '{argumentValue}' and should {constraint.Comparison} '{constraint.Value}'"); } return(formulaContext.Disqualified( argument, argumentValue, constraint.Comparison, constraint.Value)); } } foreach (var operation in formula.Operations) { decimal value = 0; switch (operation.ValueProviderName.ToLower()) { case "decimal": { value = Convert.ToDecimal(operation.InputParameter); break; } case "argument": { value = Convert.ToDecimal(executionContext.GetArgumentValue(new Guid(operation.InputParameter))); break; } case "matrix": { var matrix = GetMatrix(new Guid(operation.InputParameter)); value = Convert.ToDecimal(matrix.GetValue(_valueComparer, executionContext, GetArgument(matrix.RowArgumentId), matrix.ColumnArgumentId.HasValue ? GetArgument(matrix.ColumnArgumentId.Value) : null)); break; } case "formula": { value = Execute(executionContext, new Guid(operation.InputParameter), logger).Result; break; } case "result": { value = formulaContext.Result; break; } } if (logger.LogLevel == ContextLogLevel.Verbose) { logger.LogVerbose($"[operation] {formulaContext.Result} {operation.GetOperator()} {value}"); } operation.Perform(formulaContext, value); } return(formulaContext); } }