Skip to content

Commit

Permalink
Upgrade to NCalc v5.0.0 (#427)
Browse files Browse the repository at this point in the history
  • Loading branch information
axunonb committed Jul 1, 2024
1 parent 2fc39ef commit 20d07e1
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 19 deletions.
29 changes: 19 additions & 10 deletions src/SmartFormat.Extensions.LogiCalc/LogiCalcFormatter.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -27,6 +26,7 @@ namespace SmartFormat.Extensions;
/// </remarks>
public class LogiCalcFormatter : IFormatter
{
// Todo: Make the cache static and thread-safe?
private readonly Dictionary<string, object?> _parameters = new(50);

[ThreadStatic] // creates isolated versions of the cache dictionary in each thread
Expand All @@ -46,14 +46,14 @@ public class LogiCalcFormatter : IFormatter
public IReadOnlyDictionary<string, object?> NCalcParameters => _parameters;

/// <summary>
/// Gets or sets the <see cref="NCalc.Handlers.EvaluateFunctionHandler"/>.
/// Contains the functions that can be used in the NCalc expressions.
/// </summary>
public NCalc.Handlers.EvaluateFunctionHandler? EvaluateFunction { get; set; }
public Dictionary<string, NCalc.ExpressionFunction> Functions { get; } = new();

/// <summary>
/// Gets or sets the <see cref="NCalc.Handlers.EvaluateParameterHandler"/>.
/// Contains the dynamic parameters than can be used in the NCalc expressions.
/// </summary>
public NCalc.Handlers.EvaluateParameterHandler? EvaluateParameter { get; set; }
public Dictionary<string, object?> Parameters { get; } = new();

///<inheritdoc />
public bool TryEvaluateFormat(IFormattingInfo formattingInfo)
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ It uses extensions to provide named placeholders, localization, pluralization, g
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="NCalcSync.signed" Version="4.3.3" />
<PackageReference Include="NCalcSync.signed" Version="5.0.0" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'net462' or '$(TargetFramework)' == 'netStandard2.0'">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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})}";

Expand All @@ -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]}";

Expand Down

0 comments on commit 20d07e1

Please sign in to comment.