### Install nbgv tool Source: http://ncalc.gumbarros.com.br/articles/project/new_release.html Install the Nerdbank.GitVersioning dotnet CLI tool globally. ```bash dotnet tool install --global nbgv ``` -------------------------------- ### Services Property Source: http://ncalc.gumbarros.com.br/api/NCalc.DependencyInjection.NCalcServiceBuilder.html Gets the IServiceCollection associated with this builder. ```APIDOC ## Services Property ### Description Gets the IServiceCollection associated with this builder. ### Property `public IServiceCollection Services { get; }` ### Property Value - **IServiceCollection** - The service collection. ``` -------------------------------- ### Catch NCalcParserException and NCalcEvaluationException during evaluation Source: http://ncalc.gumbarros.com.br/articles/evaluation/handling_errors.html Wrap the Evaluate() call in a try-catch block to handle syntax errors (NCalcParserException) and evaluation errors (NCalcEvaluationException). The example uses an expression with a missing closing parenthesis to trigger the parser exception. ```csharp try { new Expression("(3 + 2").Evaluate(); } catch (NCalcParserException ex) { Console.WriteLine("Error parsing the expression: {0}", ex.Message); } catch (NCalcEvaluationException ex) { Console.WriteLine("Error evaluating the expression: {0}", ex.Message); } ``` -------------------------------- ### Switch to release branch Source: http://ncalc.gumbarros.com.br/articles/project/new_release.html Switch to the release branch created by nbgv prepare-release. ```bash git checkout release/v1.0 ``` -------------------------------- ### Build NuGet packages Source: http://ncalc.gumbarros.com.br/articles/project/new_release.html Build NuGet packages in Release configuration to verify the version number. ```bash dotnet pack -c Release ``` -------------------------------- ### Prepare release branch Source: http://ncalc.gumbarros.com.br/articles/project/new_release.html Create a stable release branch for the upcoming release. ```bash nbgv prepare-release ``` -------------------------------- ### Configure and evaluate an expression with ExpressionConfiguration Source: http://ncalc.gumbarros.com.br/articles/evaluation/configuration.html Shows how to create a reusable ExpressionConfiguration with parser and evaluation options, then use it with a new ExpressionContext per evaluation. The context holds parameters and is not thread-safe, so create a new one for each evaluation. ```csharp public static class PriceCalculator { private static readonly ExpressionConfiguration Configuration = new( new LogicalExpressionParserOptions { AllowCharValues = true }, new ExpressionEvaluationOptions { StringComparer = StringComparer.OrdinalIgnoreCase }); public static decimal Calculate(decimal price) { var context = new ExpressionContext { Parameters = { ["Price"] = price } }; var expression = new Expression("[Price] * 2", Configuration, context); return expression.Evaluate(); } } ``` -------------------------------- ### Create(string, LogicalExpressionParserOptions?, CultureInfo?, CancellationToken) Source: http://ncalc.gumbarros.com.br/api/NCalc.Factories.ILogicalExpressionFactory.html Creates a LogicalExpression from a string expression, with optional parser options, culture info, and cancellation token. ```APIDOC ## Create(string, LogicalExpressionParserOptions?, CultureInfo?, CancellationToken) ### Description Creates a LogicalExpression from the given string expression, using optional parser options, culture information, and a cancellation token. ### Method Create ### Signature ```csharp LogicalExpression Create(string expression, LogicalExpressionParserOptions? options = null, CultureInfo? cultureInfo = null, CancellationToken cancellationToken = default) ``` ### Parameters - **expression** (string) - Required - The expression string to parse. - **options** (LogicalExpressionParserOptions?) - Optional - Parser options. - **cultureInfo** (CultureInfo?) - Optional - Culture information for parsing. - **cancellationToken** (CancellationToken) - Optional - Cancellation token. ### Returns - **LogicalExpression** - The created logical expression. ``` -------------------------------- ### Copy an ExpressionContext Source: http://ncalc.gumbarros.com.br/articles/evaluation/expression_context.html Creates a copy of an existing ExpressionContext using the constructor that takes another context. The copy has new dictionaries for parameters and functions, so modifying copy.Parameters does not affect original. Parameter values, function delegates, and event handlers are copied by reference. ```csharp var original = new ExpressionContext { Parameters = { ["Price"] = 12.5m, ["Quantity"] = 4 } }; var copy = new ExpressionContext(original); copy.Parameters["Quantity"] = 10; ``` -------------------------------- ### Create ExpressionContext with parameters and functions Source: http://ncalc.gumbarros.com.br/articles/evaluation/expression_context.html Creates an ExpressionContext with parameters and a function, then evaluates an expression that uses them. The function SecretOperation returns 42. ```csharp var context = new ExpressionContext { Parameters = { ["Price"] = 12.5m, ["Quantity"] = 4 }, Functions = { ["SecretOperation"] = _ => 42 } }; var expression = new Expression("Price * Quantity + SecretOperation()", context); var result = expression.Evaluate(); ``` -------------------------------- ### Use ExpressionConfiguration and ExpressionContext together Source: http://ncalc.gumbarros.com.br/articles/evaluation/expression_context.html Passes both an ExpressionConfiguration and an ExpressionContext to the Expression constructor. The configuration sets IgnoreCaseAtBuiltInFunctions to true, allowing the built-in function ABS to be called with uppercase letters. ```csharp var configuration = new ExpressionConfiguration { Evaluation = new ExpressionEvaluationOptions { IgnoreCaseAtBuiltInFunctions = true } }; var context = new ExpressionContext { Parameters = { ["Value"] = -42 } }; var expression = new Expression("ABS(Value)", configuration, context); var result = expression.Evaluate(); ``` -------------------------------- ### WithMemoryCache Source: http://ncalc.gumbarros.com.br/api/NCalc.Cache.Configuration.NCalcServiceBuilderExtensions.html Extension method to replace the default cache with Microsoft.Extensions.MemoryCache. ```APIDOC ## WithMemoryCache(NCalcServiceBuilder, Action?) ### Description Replaces NCalc default cache with Microsoft.Extensions.MemoryCache. ### Method WithMemoryCache ### Signature public static NCalcServiceBuilder WithMemoryCache(this NCalcServiceBuilder builder, Action? configureOptions = null) ### Parameters - **builder** (NCalcServiceBuilder) - Required - The builder instance. - **configureOptions** (Action) - Optional - The options of the cache. ### Returns NCalcServiceBuilder ``` -------------------------------- ### WithExpressionFactory() Method Source: http://ncalc.gumbarros.com.br/api/NCalc.DependencyInjection.NCalcServiceBuilder.html Registers a custom IExpressionFactory implementation for creating expressions. ```APIDOC ## WithExpressionFactory() ### Description Registers a custom IExpressionFactory implementation for creating expressions. ### Method `public NCalcServiceBuilder WithExpressionFactory() where TExpressionFactory : class, IExpressionFactory` ### Type Parameters - **TExpressionFactory** - The factory type that implements IExpressionFactory. ### Returns - **NCalcServiceBuilder** - The builder instance for chaining. ``` -------------------------------- ### WithEvaluationVisitorFactory() Method Source: http://ncalc.gumbarros.com.br/api/NCalc.DependencyInjection.NCalcServiceBuilder.html Registers a custom IEvaluationVisitorFactory implementation for creating evaluation visitors. ```APIDOC ## WithEvaluationVisitorFactory() ### Description Registers a custom IEvaluationVisitorFactory implementation for creating evaluation visitors. ### Method `public NCalcServiceBuilder WithEvaluationVisitorFactory() where TEvaluationVisitorFactory : class, IEvaluationVisitorFactory` ### Type Parameters - **TEvaluationVisitorFactory** - The factory type that implements IEvaluationVisitorFactory. ### Returns - **NCalcServiceBuilder** - The builder instance for chaining. ``` -------------------------------- ### Compile hot expressions with NCalc.LambdaCompilation Source: http://ncalc.gumbarros.com.br/articles/runtime/performance.html For very hot expressions compatible with lambda compilation, use ToLambda to compile once and cache the delegate. Compiling is expensive, but invoking the compiled delegate many times is fast. ```csharp var expression = new Expression("A + B"); var lambda = expression.ToLambda(); var result = lambda(new MyContext { A = 1, B = 2 }); ``` -------------------------------- ### NCalcServiceBuilder Constructor Source: http://ncalc.gumbarros.com.br/api/NCalc.DependencyInjection.NCalcServiceBuilder.html Initializes a new instance of the NCalcServiceBuilder class with the specified IServiceCollection. ```APIDOC ## NCalcServiceBuilder(IServiceCollection) ### Description Initializes a new instance of the NCalcServiceBuilder class with the specified service collection. ### Constructor `public NCalcServiceBuilder(IServiceCollection services)` ### Parameters - **services** (IServiceCollection) - Required - The service collection to configure. ``` -------------------------------- ### Create ExpressionContext per evaluation in a service Source: http://ncalc.gumbarros.com.br/articles/evaluation/expression_context.html Shows a service that creates a new ExpressionContext per evaluation call, as recommended because ExpressionContext is mutable and not thread-safe. The context is constructed from the provided parameters dictionary and used with the injected configuration. ```csharp public class EvaluationService(ExpressionConfiguration configuration) { public object? Evaluate(string expressionText, IDictionary parameters) { var context = new ExpressionContext(parameters); var expression = new Expression(expressionText, configuration, context); return expression.Evaluate(); } } ``` -------------------------------- ### Register NCalc with logging using NCalc.DependencyInjection Source: http://ncalc.gumbarros.com.br/articles/runtime/logging.html Registers NCalc with DI and configures console logging at Information level. With default registrations, ILogicalExpressionCache is created by DI, so cache events are logged through ILogger. ```csharp using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using NCalc.DependencyInjection; var services = new ServiceCollection(); services.AddLogging(builder => { builder.AddConsole(); builder.SetMinimumLevel(LogLevel.Information); }); services.AddNCalc(); ``` -------------------------------- ### Use legacy ExpressionOptions flags Source: http://ncalc.gumbarros.com.br/articles/evaluation/configuration.html Uses the legacy ExpressionOptions flags to configure an expression. This converts the flags into an ExpressionConfiguration via FromOptions. ```csharp var expression = new Expression("1.2 + 3.4", ExpressionOptions.DecimalAsDefault | ExpressionOptions.CaseInsensitiveStringComparer); ``` -------------------------------- ### Push tags Source: http://ncalc.gumbarros.com.br/articles/project/new_release.html Push the tag created by nbgv tag to the remote repository. ```bash git push origin v1.0.7 ``` -------------------------------- ### Register ExpressionConfiguration as a singleton with DI Source: http://ncalc.gumbarros.com.br/articles/evaluation/configuration.html Registers an immutable ExpressionConfiguration as a singleton in the dependency injection container. Because the configuration is thread-safe, it can be shared across expressions. ```csharp builder.Services.AddSingleton(new ExpressionConfiguration { Parsing = new LogicalExpressionParserOptions { FloatingPointNumberType = FloatingPointNumberType.Decimal }, Evaluation = new ExpressionEvaluationOptions { StringComparer = StringComparer.OrdinalIgnoreCase, Math = new MathOptions { FloatingPointNumberType = FloatingPointNumberType.Decimal, OverflowProtection = true } } }); ``` -------------------------------- ### Cache ExpressionConfiguration as a singleton Source: http://ncalc.gumbarros.com.br/articles/runtime/performance.html Create an ExpressionConfiguration once and register it as a singleton in the service container. The configuration is thread-safe when treated as immutable, so it can be reused across evaluations. ```csharp builder.Services.AddSingleton(new ExpressionConfiguration { Evaluation = new ExpressionEvaluationOptions { StringComparer = StringComparer.OrdinalIgnoreCase, Math = new MathOptions { OverflowProtection = true } } }); ``` -------------------------------- ### Inject ExpressionConfiguration into a rule evaluator Source: http://ncalc.gumbarros.com.br/articles/evaluation/configuration.html Injects the singleton ExpressionConfiguration into a service that creates and evaluates expressions. The factory creates an expression with the shared configuration, and parameters are set on the expression before evaluation. ```csharp public class RuleEvaluator( IExpressionFactory expressionFactory, ExpressionConfiguration configuration) { public object? Evaluate(string expressionText, IDictionary parameters) { var expression = expressionFactory.Create(expressionText, configuration); expression.Parameters = parameters; return expression.Evaluate(); } } ``` -------------------------------- ### Use case-insensitive dictionary for parameters Source: http://ncalc.gumbarros.com.br/articles/runtime/performance.html Use a dictionary with StringComparer.OrdinalIgnoreCase for parameters when case-insensitive names are needed, instead of normalizing names on each call. This avoids the overhead of event handlers and dynamic callbacks for simple values. ```csharp var context = new ExpressionContext { Parameters = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["tenantId"] = 42 } }; ``` -------------------------------- ### WithLogicalExpressionFactory() Method Source: http://ncalc.gumbarros.com.br/api/NCalc.DependencyInjection.NCalcServiceBuilder.html Registers a custom ILogicalExpressionFactory implementation for creating logical expressions. ```APIDOC ## WithLogicalExpressionFactory() ### Description Registers a custom ILogicalExpressionFactory implementation for creating logical expressions. ### Method `public NCalcServiceBuilder WithLogicalExpressionFactory() where TLogicalExpressionFactory : class, ILogicalExpressionFactory` ### Type Parameters - **TLogicalExpressionFactory** - The factory type that implements ILogicalExpressionFactory. ### Returns - **NCalcServiceBuilder** - The builder instance for chaining. ``` -------------------------------- ### WithCache() Method Source: http://ncalc.gumbarros.com.br/api/NCalc.DependencyInjection.NCalcServiceBuilder.html Registers a custom ILogicalExpressionCache implementation for caching logical expressions. ```APIDOC ## WithCache() ### Description Registers a custom ILogicalExpressionCache implementation for caching logical expressions. ### Method `public NCalcServiceBuilder WithCache() where TCache : class, ILogicalExpressionCache` ### Type Parameters - **TCache** - The cache type that implements ILogicalExpressionCache. ### Returns - **NCalcServiceBuilder** - The builder instance for chaining. ``` -------------------------------- ### Set ExpressionOptions on an existing expression Source: http://ncalc.gumbarros.com.br/articles/evaluation/configuration.html Sets the Options property on an existing expression, which replaces its current Configuration with the one created by FromOptions(ExpressionOptions). ```csharp var expression = new Expression("Round(22.5, 0)"); expression.Options = ExpressionOptions.RoundAwayFromZero; ``` -------------------------------- ### Pass CancellationToken to EvaluateAsync with custom async function Source: http://ncalc.gumbarros.com.br/articles/runtime/cancellation.html Shows how to pass a CancellationToken to EvaluateAsync and forward it to a custom async function. The handler must call ThrowIfCancellationRequested and pass the token to async operations; NCalc only cancels at parsing, not during evaluation. ```csharp var cts = new CancellationTokenSource(); var expression = new Expression("getUserName(1) == 'admin'"); expression.AsyncFunctions["getUserName"] = async args => { var id = Convert.ToInt32(await args[0].EvaluateAsync(args.CancellationToken)); args.CancellationToken.ThrowIfCancellationRequested(); using var db = new AppDbContext(); return await db.Users .Where(u => u.Id == id) .Select(u => u.Name) .FirstAsync(args.CancellationToken); }; var result = await expression.EvaluateAsync(cts.Token); ``` -------------------------------- ### Tag release branch Source: http://ncalc.gumbarros.com.br/articles/project/new_release.html Tag the last commit on the release branch with the current version number. ```bash nbgv tag release/v1.0 ``` -------------------------------- ### Reuse Expression instance for repeated evaluation Source: http://ncalc.gumbarros.com.br/articles/runtime/performance.html Keep the Expression instance and update only its runtime parameters when evaluating the same expression text repeatedly. Avoid caching ExpressionContext as shared mutable state; create a new context for each evaluation scope. ```csharp var expression = new Expression("Price * Quantity", configuration); expression.Parameters["Price"] = 10m; expression.Parameters["Quantity"] = 2; var first = expression.Evaluate(); expression.Parameters["Price"] = 12m; expression.Parameters["Quantity"] = 4; var second = expression.Evaluate(); ``` -------------------------------- ### Detect syntax errors with HasErrors() Source: http://ncalc.gumbarros.com.br/articles/evaluation/handling_errors.html Use the HasErrors() method to check for syntax errors before evaluation. If errors exist, the Error property contains the error message. ```csharp var expression = new Expression("a + b * ("); if(expression.HasErrors()) { Console.WriteLine(expression.Error); } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.