{"id":13457930,"url":"https://github.com/dynamicexpresso/DynamicExpresso","last_synced_at":"2025-03-24T14:32:29.464Z","repository":{"id":6477500,"uuid":"7717596","full_name":"dynamicexpresso/DynamicExpresso","owner":"dynamicexpresso","description":"C# expressions interpreter","archived":false,"fork":false,"pushed_at":"2025-03-08T08:35:26.000Z","size":1507,"stargazers_count":2069,"open_issues_count":39,"forks_count":390,"subscribers_count":97,"default_branch":"master","last_synced_at":"2025-03-20T09:01:40.294Z","etag":null,"topics":["c-sharp","expression-evaluator","lambda-expressions"],"latest_commit_sha":null,"homepage":"http://dynamic-expresso.azurewebsites.net/","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dynamicexpresso.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["davideicardi","metoule"]}},"created_at":"2013-01-20T15:07:16.000Z","updated_at":"2025-03-16T16:20:45.000Z","dependencies_parsed_at":"2023-01-13T14:00:50.815Z","dependency_job_id":"44db1e9b-29de-4aea-b246-6e222ff849f7","html_url":"https://github.com/dynamicexpresso/DynamicExpresso","commit_stats":{"total_commits":254,"total_committers":31,"mean_commits":8.193548387096774,"dds":0.3700787401574803,"last_synced_commit":"65bdcbad729194f0be0a8aa08bf4a7795a33da9a"},"previous_names":["davideicardi/dynamicexpresso"],"tags_count":58,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dynamicexpresso%2FDynamicExpresso","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dynamicexpresso%2FDynamicExpresso/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dynamicexpresso%2FDynamicExpresso/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dynamicexpresso%2FDynamicExpresso/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dynamicexpresso","download_url":"https://codeload.github.com/dynamicexpresso/DynamicExpresso/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245084610,"owners_count":20558248,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c-sharp","expression-evaluator","lambda-expressions"],"created_at":"2024-07-31T09:00:39.894Z","updated_at":"2025-03-24T14:32:29.450Z","avatar_url":"https://github.com/dynamicexpresso.png","language":"C#","funding_links":["https://github.com/sponsors/davideicardi","https://github.com/sponsors/metoule"],"categories":["C\\#","others","C#"],"sub_categories":[],"readme":"# Dynamic Expresso\n\n[![NuGet version](https://badge.fury.io/nu/DynamicExpresso.Core.svg)](http://badge.fury.io/nu/DynamicExpresso.Core)\n[![.NET CI](https://github.com/dynamicexpresso/DynamicExpresso/actions/workflows/ci.yml/badge.svg)](https://github.com/dynamicexpresso/DynamicExpresso/actions/workflows/ci.yml)\n\nSupported platforms: .NET Core 3.1, .NET Core 5.0 and above, .NET 4.6.2\n\nDynamic Expresso is an interpreter for simple C# statements written in .NET Standard 2.0.\nDynamic Expresso embeds its own parsing logic, really interprets C# statements by converting it to .NET lambda expressions or delegates.\n\nUsing Dynamic Expresso developers can create scriptable applications, execute .NET code without compilation or create dynamic linq statements. \n\nStatements are written using a subset of C# language specifications. Global variables or parameters can be injected and used inside expressions. It doesn't generate assembly but it creates an expression tree on the fly. \n\n![dynamic expresso workflow](https://raw.github.com/dynamicexpresso/DynamicExpresso/master/docs/workflow.png \"dynamic expresso workflow\")\n\nFor example you can evaluate math expressions:\n```csharp\nvar interpreter = new Interpreter();\nvar result = interpreter.Eval(\"8 / 2 + 2\");\n```\nor parse an expression with variables or parameters and invoke it multiple times:\n```csharp\nvar interpreter = new Interpreter().SetVariable(\"service\", new ServiceExample());\nstring expression = \"x \u003e 4 ? service.OneMethod() : service.AnotherMethod()\";\nLambda parsedExpression = interpreter.Parse(expression, new Parameter(\"x\", typeof(int)));\nvar result = parsedExpression.Invoke(5);\n```\nor generate delegates and lambda expressions for LINQ queries:\n```csharp\nvar prices = new [] { 5, 8, 6, 2 };\nvar whereFunction = new Interpreter().ParseAsDelegate\u003cFunc\u003cint, bool\u003e\u003e(\"arg \u003e 5\");\nvar count = prices.Where(whereFunction).Count();\n```\n## Live demo\nDynamic Expresso live demo: [http://dynamic-expresso.azurewebsites.net/](http://dynamic-expresso.azurewebsites.net/)\n\n## Quick start\nDynamic Expresso is available on [NuGet]. You can install the package using:\n\n\tPM\u003e Install-Package DynamicExpresso.Core\n\nSource code and symbols (.pdb files) for debugging are available on [Symbol Source].\n\n## Features\n- Expressions can be written using a subset of C# syntax (see Syntax section for more information)\n- Support for variables and parameters\n- Can generate delegates or lambda expression\n- Full suite of unit tests\n- Good performance compared to other similar projects\n- Partial support of generic, params array and extension methods (only with implicit generic arguments detection)\n- Partial support of `dynamic` (`ExpandoObject` for get properties, method invocation and indexes(#142), see #72. `DynamicObject` for get properties and indexes, see #142)\n- Partial support of lambda expressions (disabled by default, because it has a slight performance penalty)\n- Case insensitive expressions (default is case sensitive)\n- Ability to discover identifiers (variables, types, parameters) of a given expression\n- Small footprint, generated expressions are managed classes, can be unloaded and can be executed in a single appdomain\n- Easy to use and deploy, it is all contained in a single assembly without other external dependencies\n- Written in .NET Standard 2.0\n\t- Build available for .NET 4.6.1 and .NET Core 2.0\n- Open source (MIT license)\n\n### Return value\nYou can parse and execute void expression (without a return value) or you can return any valid .NET type. \nWhen parsing an expression you can specify the expected expression return type. For example you can write:\n```csharp\nvar target = new Interpreter();\ndouble result = target.Eval\u003cdouble\u003e(\"Math.Pow(x, y) + 5\",\n\t\t\t\t    new Parameter(\"x\", typeof(double), 10),\n\t\t\t\t    new Parameter(\"y\", typeof(double), 2));\n```\nThe built-in parser can also understand the return type of any given expression so you can check if the expression returns what you expect.\n\n### Variables\nVariables can be used inside expressions with `Interpreter.SetVariable` method:\n```csharp\nvar target = new Interpreter().SetVariable(\"myVar\", 23);\n\nAssert.That(target.Eval(\"myVar\"), Is.EqualTo(23));\n```\nVariables can be primitive types or custom complex types (classes, structures, delegates, arrays, collections, ...).\n\nCustom functions can be passed with delegate variables using `Interpreter.SetFunction` method:\n```csharp\nFunc\u003cdouble, double, double\u003e pow = (x, y) =\u003e Math.Pow(x, y);\nvar target = new Interpreter().SetFunction(\"pow\", pow);\n\nAssert.That(target.Eval(\"pow(3, 2)\"), Is.EqualTo(9.0));\n```\nCustom [Expression](http://msdn.microsoft.com/en-us/library/system.linq.expressions.expression.aspx) can be passed by using `Interpreter.SetExpression` method.\n\n\n### Parameters\nParsed expressions can accept one or more parameters:\n```csharp\nvar interpreter = new Interpreter();\n\nvar parameters = new[] {\n\tnew Parameter(\"x\", 23),\n\tnew Parameter(\"y\", 7)\n};\n\nAssert.That(interpreter.Eval(\"x + y\", parameters), Is.EqualTo(30));\n```\nParameters can be primitive types or custom types. You can parse an expression once and invoke it multiple times with different parameter values:\n```csharp\nvar target = new Interpreter();\n\nvar parameters = new[] {\n\tnew Parameter(\"x\", typeof(int)),\n\tnew Parameter(\"y\", typeof(int))\n};\n\nvar myFunc = target.Parse(\"x + y\", parameters);\n\nAssert.That(myFunc.Invoke(23, 7), Is.EqualTo(30));\nAssert.That(myFunc.Invoke(32, -2), Is.EqualTo(30));\n```\n\n### Special identifiers\n\nEither a variable or a parameter with name `this` can be referenced implicitly.\n\n```csharp\nclass Customer { public string Name { get; set; } }\n\nvar target = new Interpreter();\n\n// 'this' is treated as a special identifier and can be accessed implicitly \ntarget.SetVariable(\"this\", new Customer { Name = \"John\" });\n\n// explicit context reference via 'this' variable\nAssert.That(target.Eval(\"this.Name\"), Is.EqualTo(\"John\"));\n\n// 'this' variable is referenced implicitly\nAssert.That(target.Eval(\"Name\"), Is.EqualTo(\"John\"));\n```\n\n### Built-in types and custom types\nCurrently predefined types available are:\n\n\tObject object \n\tBoolean bool \n\tChar char\n\tString string\n\tSByte Byte byte\n\tInt16 UInt16 Int32 int UInt32 Int64 long UInt64 \n\tSingle Double double Decimal decimal \n\tDateTime TimeSpan\n\tGuid\n\tMath Convert\n\nYou can reference any other custom .NET type by using `Interpreter.Reference` method:\n```csharp\nvar target = new Interpreter().Reference(typeof(Uri));\n\nAssert.That(target.Eval(\"typeof(Uri)\"), Is.EqualTo(typeof(Uri)));\nAssert.That(target.Eval(\"Uri.UriSchemeHttp\"), Is.EqualTo(Uri.UriSchemeHttp));\n```\n\n### Generate dynamic delegates\nYou can use the `Interpreter.ParseAsDelegate\u003cTDelegate\u003e` method to directly parse an expression into a .NET delegate type that can be normally invoked. \nIn the example below I generate a `Func\u003cCustomer, bool\u003e` delegate that can be used in a LINQ where expression.\n```csharp\nclass Customer\n{\n\tpublic string Name { get; set; }\n\tpublic int Age { get; set; }\n\tpublic char Gender { get; set; }\n}\n\n[Test]\npublic void Linq_Where()\n{\n\tvar customers = new List\u003cCustomer\u003e {\n\t\tnew Customer() { Name = \"David\", Age = 31, Gender = 'M' },\n\t\tnew Customer() { Name = \"Mary\", Age = 29, Gender = 'F' },\n\t\tnew Customer() { Name = \"Jack\", Age = 2, Gender = 'M' },\n\t\tnew Customer() { Name = \"Marta\", Age = 1, Gender = 'F' },\n\t\tnew Customer() { Name = \"Moses\", Age = 120, Gender = 'M' },\n\t};\n\n\tstring whereExpression = \"customer.Age \u003e 18 \u0026\u0026 customer.Gender == 'F'\";\n\n\tvar interpreter = new Interpreter();\n\tFunc\u003cCustomer, bool\u003e dynamicWhere = interpreter.ParseAsDelegate\u003cFunc\u003cCustomer, bool\u003e\u003e(whereExpression, \"customer\");\n\n\tAssert.That(customers.Where(dynamicWhere).Count(), Is.EqualTo(1));\n}\n```\nThis is the preferred way to parse an expression that you known at compile time what parameters can accept and what value must return.\n\n### Generate lambda expressions\nYou can use the `Interpreter.ParseAsExpression\u003cTDelegate\u003e` method to directly parse an expression into a .NET lambda expression (`Expression\u003cTDelegate\u003e`). \n\nIn the example below I generate a `Expression\u003cFunc\u003cCustomer, bool\u003e\u003e` expression that can be used in a Queryable LINQ where expression or in any other place where an expression is required. Like Entity Framework or other similar libraries.\n```csharp\nclass Customer\n{\n\tpublic string Name { get; set; }\n\tpublic int Age { get; set; }\n\tpublic char Gender { get; set; }\n}\n\n[Test]\npublic void Linq_Queryable_Expression_Where()\n{\n\tIQueryable\u003cCustomer\u003e customers = (new List\u003cCustomer\u003e {\n\t\tnew Customer() { Name = \"David\", Age = 31, Gender = 'M' },\n\t\tnew Customer() { Name = \"Mary\", Age = 29, Gender = 'F' },\n\t\tnew Customer() { Name = \"Jack\", Age = 2, Gender = 'M' },\n\t\tnew Customer() { Name = \"Marta\", Age = 1, Gender = 'F' },\n\t\tnew Customer() { Name = \"Moses\", Age = 120, Gender = 'M' },\n\t}).AsQueryable();\n\n\tstring whereExpression = \"customer.Age \u003e 18 \u0026\u0026 customer.Gender == 'F'\";\n\n\tvar interpreter = new Interpreter();\n\tExpression\u003cFunc\u003cCustomer, bool\u003e\u003e expression = interpreter.ParseAsExpression\u003cFunc\u003cCustomer, bool\u003e\u003e(whereExpression, \"customer\");\n\n\tAssert.That(customers.Where(expression).Count(), Is.EqualTo(1));\n}\n```\n\n## Syntax and operators\nStatements can be written using a subset of the C# syntax. Here you can find a list of the supported expressions: \n\n### Operators\n\nSupported operators:\n\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003cth\u003eCategory\u003c/th\u003e\u003cth\u003eOperators\u003c/th\u003e\n\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003ePrimary\u003c/td\u003e\u003ctd\u003e\u003ccode\u003ex.y  f(x)  a[x]  new  typeof\u003c/code\u003e\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003eUnary\u003c/td\u003e\u003ctd\u003e\u003ccode\u003e+  -  !  (T)x\u003c/code\u003e\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003eMultiplicative\u003c/td\u003e\u003ctd\u003e\u003ccode\u003e*  /  %\u003c/code\u003e\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003eAdditive\u003c/td\u003e\u003ctd\u003e\u003ccode\u003e+  -\u003c/code\u003e\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003eRelational and type testing\u003c/td\u003e\u003ctd\u003e\u003ccode\u003e\u0026lt;  \u0026gt;  \u0026lt;=  \u0026gt;=  is  as\u003c/code\u003e\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003eEquality\u003c/td\u003e\u003ctd\u003e\u003ccode\u003e==  !=\u003c/code\u003e\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003eLogical AND\u003c/td\u003e\u003ctd\u003e\u003ccode\u003e\u0026\u003c/code\u003e\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003eLogical OR\u003c/td\u003e\u003ctd\u003e\u003ccode\u003e|\u003c/code\u003e\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003eLogical XOR\u003c/td\u003e\u003ctd\u003e\u003ccode\u003e^\u003c/code\u003e\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003eConditional AND\u003c/td\u003e\u003ctd\u003e\u003ccode\u003e\u0026\u0026\u003c/code\u003e\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003eConditional OR\u003c/td\u003e\u003ctd\u003e\u003ccode\u003e||\u003c/code\u003e\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003eConditional\u003c/td\u003e\u003ctd\u003e\u003ccode\u003e?:\u003c/code\u003e\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003eAssignment\u003c/td\u003e\u003ctd\u003e\u003ccode\u003e=\u003c/code\u003e\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003eNull coalescing\u003c/td\u003e\u003ctd\u003e\u003ccode\u003e??\u003c/code\u003e\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\nOperators precedence is respected following [C# rules (Operator precedence and associativity)](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/).\n\nSome operators, like the assignment operator, can be disabled for security reason.\n\n### Literals\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003cth\u003eCategory\u003c/th\u003e\u003cth\u003eOperators\u003c/th\u003e\n\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003eConstants\u003c/td\u003e\u003ctd\u003e\u003ccode\u003etrue  false  null\u003c/code\u003e\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003eReal literal suffixes\u003c/td\u003e\u003ctd\u003e\u003ccode\u003ed  f  m\u003c/code\u003e\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003eInteger literal suffixes\u003c/td\u003e\u003ctd\u003e\u003ccode\u003eu l ul lu\u003c/code\u003e\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\t\u003ctr\u003e\n\t\t\t\u003ctd\u003eString/char\u003c/td\u003e\u003ctd\u003e\u003ccode\u003e\"\"  ''\u003c/code\u003e\u003c/td\u003e\n\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\nThe following character escape sequences are supported inside string or char literals:\n\n- `\\'` - single quote, needed for character literals\n- `\\\"` - double quote, needed for string literals\n- `\\\\` - backslash\n- `\\0` - Unicode character 0\n- `\\a` - Alert (character 7)\n- `\\b` - Backspace (character 8)\n- `\\f` - Form feed (character 12)\n- `\\n` - New line (character 10)\n- `\\r` - Carriage return (character 13)\n- `\\t` - Horizontal tab (character 9)\n- `\\v` - Vertical quote (character 11)\n\n### Type's members invocation\n\nAny standard .NET method, field, property or constructor can be invoked.\n```csharp\nvar service = new MyTestService();\nvar context = new MyTestContext();\n\nvar target = new Interpreter()\n  .SetVariable(\"x\", service)\n  .SetVariable(\"this\", context);\n\nAssert.That(target.Eval(\"x.HelloWorld()\"), Is.EqualTo(service.HelloWorld()));\nAssert.That(target.Eval(\"x.AProperty\"), Is.EqualTo(service.AProperty));\nAssert.That(target.Eval(\"x.AField\"), Is.EqualTo(service.AField));\n\n// implicit context reference\nAssert.That(target.Eval(\"GetContextId()\"), Is.EqualTo(context.GetContextId()));\nAssert.That(target.Eval(\"ContextName\"), Is.EqualTo(context.ContextName));\nAssert.That(target.Eval(\"ContextField\"), Is.EqualTo(context.ContextField));\n```\n```csharp\nvar target = new Interpreter();\nAssert.That(target.Eval(\"new DateTime(2015, 1, 24)\"), Is.EqualTo(new DateTime(2015, 1, 24));\n```\nDynamic Expresso also supports:\n\n- Extension methods\n```csharp\nvar x = new int[] { 10, 30, 4 };\nvar target = new Interpreter()\n\t.Reference(typeof(System.Linq.Enumerable))\n\t.SetVariable(\"x\", x);\nAssert.That(target.Eval(\"x.Count()\"), Is.EqualTo(x.Count()));\n```\n- Indexer methods (like `array[0]`)\n- Generics, only partially supported (only implicit, you cannot invoke an explicit generic method)\n- Params array (see C# `params` keyword)\n\n### Lambda expressions\nDynamic Expresso has partial supports of lambda expressions. For example, you can use any Linq method:\n\n```csharp\nvar x = new string[] { \"this\", \"is\", \"awesome\" };\nvar options = InterpreterOptions.Default | InterpreterOptions.LambdaExpressions; // enable lambda expressions\nvar target = new Interpreter(options)\n\t.SetVariable(\"x\", x);\n\nvar results = target.Eval\u003cIEnumerable\u003cstring\u003e\u003e(\"x.Where(str =\u003e str.Length \u003e 5).Select(str =\u003e str.ToUpper())\");\nAssert.That(results, Is.EqualTo(new[] { \"AWESOME\" }));\n```\n\nNote that parsing lambda expressions is disabled by default, because it has a slight performance cost.\nTo enable them, you must set the `InterpreterOptions.LambdaExpressions` flag.\n\nIt's also possible to create a delegate directly from a lambda expression:\n\n```csharp\nvar options = InterpreterOptions.Default | InterpreterOptions.LambdaExpressions; // enable lambda expressions\nvar target = new Interpreter(options)\n\t.SetVariable(\"increment\", 3); // access a variable from the lambda expression\n\nvar myFunc = target.Eval\u003cFunc\u003cint, string, string\u003e\u003e(\"(i, str) =\u003e str.ToUpper() + (i + increment)\");\nAssert.That(lambda.Invoke(5, \"test\"), Is.EqualTo(\"TEST8\"));\n```\n\n### Case sensitive/insensitive\nBy default all expressions are considered case sensitive (`VARX` is different than `varx`, as in C#).\nThere is an option to use a case insensitive parser. For example:\n```csharp\nvar target = new Interpreter(InterpreterOptions.DefaultCaseInsensitive);\n\ndouble x = 2;\nvar parameters = new[] {\n\tnew Parameter(\"x\", x.GetType(), x)\n};\n\nAssert.That(target.Eval(\"x\", parameters), Is.EqualTo(x));\nAssert.That(target.Eval(\"X\", parameters), Is.EqualTo(x));\n```\n\n\n\n## Identifiers detection\nSometimes you need to check which identifiers (variables, types, parameters) are used in expression before parsing it.\nMaybe because you want to validate it or you want to ask the user to enter parameters value of a given expression.\nBecause if you parse an expression without the right parameter an exception is throwed.\n\nIn these cases you can use `Interpreter.DetectIdentifiers` method to obtain a list of used identifiers, both known and unknown.\n```csharp\nvar target = new Interpreter();\n\nvar detectedIdentifiers = target.DetectIdentifiers(\"x + y\");\n\nAssert.That(detectedIdentifiers.UnknownIdentifiers, \n        Is.EqualTo(new[] { \"x\", \"y\" });\n```\n\n## Default number type\nIn C #, numbers are usually interpreted as integers or doubles if they have decimal places.\n\nIn some cases it may be useful to be able to configure the default type of numbers if no particular suffix is ​​specified: for example in financial calculations, where usually numbers are interpreted as decimal type.\n\nIn these cases you can set the default number type using `Interpreter.SetDefaultNumberType`  method.\n\n```csharp\nvar target = new Interpreter();\n\ntarget.SetDefaultNumberType(DefaultNumberType.Decimal);\n\nAssert.That(target.Eval(\"45\"), Is.InstanceOf\u003cSystem.Decimal\u003e());\nAssert.That(target.Eval(\"10/3\"), Is.EqualTo(10M/3M)); // 3.33333333333 instead of 3\n```\n\n## Limitations\nNot every C# syntaxes are supported. Here some examples of NOT supported features:\n\n- Multiline expressions\n- for/foreach/while/do operators\n- Array/list/dictionary initialization\n- Explicit generic invocation (like `method\u003ctype\u003e(arg)`) \n- Lambda/delegate declaration (delegate and lamda are only supported as variables or parameters or as a return type of the expression)\n- Array/list/dictionary element assignment (set indexer operator)\n- Other operations on `dynamic` objects (only property, method invocation and index now are supported)\n\n## Exceptions\nIf there is an error during the parsing always an exception of type `ParseException` is throwed. \n`ParseException` has several specialization classes based on the type of error (UnknownIdentifierException, NoApplicableMethodException. ...).\n\n## Performance and multithreading\nThe `Interpreter` class can be used by multiple threads but without modify it.\nIn essence only get properties, `Parse` and `Eval` methods are thread safe. Other methods (`SetVariable`, `Reference`, ...) must be called in an initialization phase.\n`Lambda` and `Parameter` classes are completely thread safe.\n\nIf you need to run the same expression multiple times with different parameters I suggest to parse it one time and then invoke the parsed expression multiple times.\n\n## Security\nIf you allow an end user to write expression you must consider some security implications.\n\nParsed expressions can access only the .NET types that you have referenced using the `Interpreter.Reference` method or types that you pass as a variable or parameter. \nYou must pay attention of what types you expose.\nIn any case generated delegates are executed as any other delegate and standard security .NET rules can be applied (for more info see [Security in the .NET Framework](http://msdn.microsoft.com/en-us/library/fkytk30f.aspx)). \n\nIf expressions test can be written directly by users you must ensure that only certain features are available. Here some guidelines:\n\nFor example you can disable assignment operators, to ensure that the user cannot change some values that you don't expect. \nBy default assignment operators are enables, by you can disable it using:\n```csharp\nvar target = new Interpreter().EnableAssignment(AssignmentOperators.None);\n```\nFrom version 1.3 to prevent malicious users to call unexpected types or assemblies within an expression, \nsome reflection methods are blocked. For example you cannot write:\n```csharp\nvar target = new Interpreter();\ntarget.Eval(\"typeof(double).GetMethods()\");\n// or\ntarget.Eval(\"typeof(double).Assembly\");\n```\nThe only exception to this rule is the `Type.Name` property that is permitted for debugging reasons.\n To enable standard reflection features you can use `Interpreter.EnableReflection` method, like:\n```csharp\nvar target = new Interpreter().EnableReflection();\n```\n\n## Usage scenarios\nHere are some possible usage scenarios of Dynamic Expresso:\n\n- Programmable applications\n- Allow the user to inject customizable rules and logic without recompiling\n- Evaluate dynamic functions or commands\n- LINQ dynamic query\n\n## Future roadmap\n\nSee [github open issues and milestones](https://github.com/dynamicexpresso/DynamicExpresso/issues).\n\n## Help and support\n\nIf you need help you can try one of the following:\n\n- [FAQ](https://github.com/dynamicexpresso/DynamicExpresso/wiki/FAQ) wiki page\n- github [official repository](https://github.com/dynamicexpresso/DynamicExpresso)\n\n## Maintainers\n\nCurrently Dynamic Expresso is maintained by @davideicardi and @metoule.\n\n## Credits\n\nThis project is based on two old works:\n- \"Converting String expressions to Funcs with FunctionFactory by Matthew Abbott\" (link not more available) \n- DynamicQuery - Dynamic LINQ - Visual Studio 2008 sample: http://msdn.microsoft.com/en-us/vstudio/bb894665.aspx \n\nThanks to all [contributors](https://github.com/dynamicexpresso/DynamicExpresso/graphs/contributors)!\n\n## Other resources or similar projects\nBelow you can find a list of some similar projects that I have evaluated or that can be interesting to study. \nFor one reason or another none of these projects exactly fit my needs so I decided to write my own interpreter.\n\n- Roslyn Project - Scripting API - https://github.com/dotnet/roslyn/wiki/Scripting-API-Samples\n\t- This is the new Microsoft Official Compiler as a service library. I suggest to consider using Roslyin instead of DynamicExpresso for complex scenarios.\n- Mono.CSharp - C# Compiler Service and Runtime Evaulator - http://docs.go-mono.com/index.aspx?link=N%3AMono.CSharp\n- NCalc - Mathematical Expressions Evaluator for .NET - http://ncalc.codeplex.com/\n- David Wynne CSharpEval https://github.com/DavidWynne/CSharpEval\n- CSharp Eval http://csharp-eval.com/\n- C# Expression Evaluator http://csharpeval.codeplex.com/\n- Jint - Javascript interpreter for .NET - http://jint.codeplex.com/\n- Jurassic - Javascript compiler for .NET - http://jurassic.codeplex.com/\n- Javascrpt.net - javascript V8 engine - http://javascriptdotnet.codeplex.com/\n- CS-Script - http://www.csscript.net/\n- IronJS, IronRuby, IronPython\n- paxScript.NET http://eco148-88394.innterhost.net/paxscriptnet/\n\n## Continuous Integration\n\nA continuous integration pipeline is configured using Github Actions, see `.github/workflows` folder.\n\nWhenever a new [Release](https://github.com/dynamicexpresso/DynamicExpresso/releases) is created, Nuget packages are published. For snapshot releases packages are published only to Github.\nFor official releases packages are published to both GitHub and Nuget.\n\n## Compiling and run tests\n\nTo compile the solution you can run:\n\n\tdotnet build DynamicExpresso.sln -c Release\n\nTo create nuget packages:\n\n\tdotnet pack DynamicExpresso.sln -c Release\n\nTo run unit tests:\n\n\tdotnet test DynamicExpresso.sln -c Release\n\nor run unit tests for a specific project with a specific framework:\n\n\tdotnet test DynamicExpresso.sln --no-restore -c Release --verbosity normal -f netcoreapp3.1\n\nAdd `--logger:trx` to generate test results for VSTS.\n\n## Release notes\n\nSee [releases page](https://github.com/dynamicexpresso/DynamicExpresso/releases).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdynamicexpresso%2FDynamicExpresso","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdynamicexpresso%2FDynamicExpresso","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdynamicexpresso%2FDynamicExpresso/lists"}