From 20d07e137771477e5db8118b67da9345f2b834bb Mon Sep 17 00:00:00 2001 From: axunonb Date: Mon, 1 Jul 2024 16:28:48 +0200 Subject: [PATCH] Upgrade to NCalc v5.0.0 (#427) --- .../LogiCalcFormatter.cs | 29 ++++++++++++------- .../SmartFormat.Extensions.LogiCalc.csproj | 2 +- .../LogiCalcFormatterTests.cs | 10 ++----- 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/SmartFormat.Extensions.LogiCalc/LogiCalcFormatter.cs b/src/SmartFormat.Extensions.LogiCalc/LogiCalcFormatter.cs index e229eb4b..274c128c 100644 --- a/src/SmartFormat.Extensions.LogiCalc/LogiCalcFormatter.cs +++ b/src/SmartFormat.Extensions.LogiCalc/LogiCalcFormatter.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Globalization; -using NCalc.Factories; using SmartFormat.Core.Extensions; using SmartFormat.Core.Formatting; using SmartFormat.Core.Parsing; @@ -27,6 +26,7 @@ namespace SmartFormat.Extensions; /// public class LogiCalcFormatter : IFormatter { + // Todo: Make the cache static and thread-safe? private readonly Dictionary _parameters = new(50); [ThreadStatic] // creates isolated versions of the cache dictionary in each thread @@ -46,14 +46,14 @@ public class LogiCalcFormatter : IFormatter public IReadOnlyDictionary NCalcParameters => _parameters; /// - /// Gets or sets the . + /// Contains the functions that can be used in the NCalc expressions. /// - public NCalc.Handlers.EvaluateFunctionHandler? EvaluateFunction { get; set; } + public Dictionary Functions { get; } = new(); /// - /// Gets or sets the . + /// Contains the dynamic parameters than can be used in the NCalc expressions. /// - public NCalc.Handlers.EvaluateParameterHandler? EvaluateParameter { get; set; } + public Dictionary Parameters { get; } = new(); /// public bool TryEvaluateFormat(IFormattingInfo formattingInfo) @@ -78,21 +78,30 @@ public bool TryEvaluateFormat(IFormattingInfo formattingInfo) $"{{,{formattingInfo.Alignment}:d:{formattingInfo.FormatterOptions}}}"); var nCalcOptions = formattingInfo.FormatDetails.Settings.CaseSensitivity == CaseSensitivityType.CaseInsensitive - ? NCalc.ExpressionOptions.IgnoreCase + ? NCalc.ExpressionOptions.IgnoreCaseAtBuiltInFunctions : NCalc.ExpressionOptions.None; nCalcOptions |= NCalc.ExpressionOptions.NoCache; // Todo: Would this make sense? // nCalcOptions |= NCalc.ExpressionOptions.AllowNullParameter; - cache.LogExpr = LogicalExpressionFactory.Create(expressionValue.ToString(), + cache.LogExpr = NCalc.Factories.LogicalExpressionFactory.Create(expressionValue.ToString(), new NCalc.ExpressionContext(nCalcOptions, CultureInfo.InvariantCulture)); _formatNCalcCache.Add(key, cache); } - var nCalcExpression = new NCalc.Expression(cache.LogExpr) { Parameters = _parameters }; - if (EvaluateFunction != null) nCalcExpression.EvaluateFunction += EvaluateFunction; - if (EvaluateParameter != null) nCalcExpression.EvaluateParameter += EvaluateParameter; + var nCalcExpression = new NCalc.Expression(cache.LogExpr) + { + Parameters = Parameters, + Functions = Functions + }; + + // Add the parameters from the Placeholder + // Don't mix placeholder parameters with user-defined parameters + foreach (var keyValuePair in _parameters) + { + nCalcExpression.Parameters.Add(keyValuePair); + } var result = nCalcExpression.Evaluate(); formattingInfo.FormatAsChild(cache.Format, result); diff --git a/src/SmartFormat.Extensions.LogiCalc/SmartFormat.Extensions.LogiCalc.csproj b/src/SmartFormat.Extensions.LogiCalc/SmartFormat.Extensions.LogiCalc.csproj index 425929cf..41cee49e 100644 --- a/src/SmartFormat.Extensions.LogiCalc/SmartFormat.Extensions.LogiCalc.csproj +++ b/src/SmartFormat.Extensions.LogiCalc/SmartFormat.Extensions.LogiCalc.csproj @@ -24,7 +24,7 @@ It uses extensions to provide named placeholders, localization, pluralization, g all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/src/SmartFormat.Tests/Extensions.LogiCalc/LogiCalcFormatterTests.cs b/src/SmartFormat.Tests/Extensions.LogiCalc/LogiCalcFormatterTests.cs index ab58cdc2..bdff0216 100644 --- a/src/SmartFormat.Tests/Extensions.LogiCalc/LogiCalcFormatterTests.cs +++ b/src/SmartFormat.Tests/Extensions.LogiCalc/LogiCalcFormatterTests.cs @@ -118,10 +118,7 @@ public void Evaluate_Custom_Evaluation_Function() var smart = GetFormatter(); var nc = (LogiCalcFormatter) smart.GetFormatterExtensions().First(f => f.GetType() == typeof(LogiCalcFormatter)); - nc.EvaluateFunction += (name, args) => - { - if (name == "MyFunction") args.Result = ((int?) args.Parameters[0].Evaluate()) / 5; - }; + nc.Functions["MyFunction"] = args => ((int?) args[0].Evaluate()) / 5; const string format = "{:calc:MyFunction({One})}"; @@ -134,10 +131,7 @@ public void Evaluate_Custom_Parameter_Function() { var smart = GetFormatter(); var nc = (LogiCalcFormatter) smart.GetFormatterExtensions().First(f => f.GetType() == typeof(LogiCalcFormatter)); - nc.EvaluateParameter += (name, args) => - { - if (name == "MyParameter") args.Result = 1234567; - }; + nc.Parameters["MyParameter"] = 1234567; const string format = "{:calc:[MyParameter]}";