Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Variables and Functions

Coding Seb edited this pageFeb 23, 2021 ·45 revisions

Standard constants (variables)

ConstantValueType
nullC# null valueN/A
trueC# true valueSystem.Boolean
falseC# false valueSystem.Boolean
Pi3.14159265358979System.Double
E2.71828182845905System.Double

Custom variables

You can define your own variables

Examples :
Live examples here

ExpressionEvaluatorevaluator=newExpressionEvaluator();evaluator.Variables=newDictionary<string,object>(){{"x",2.5},{"y",-3.6},{"myVar","Hello World"},{"myArray",newobject[]{3.5,"Test",false}},};
x+y-1.1myVar + " !!!"Hello World !!!myArray.Length3myArray[0]3.5myArray[1].Length4myArray[2] || trueTrue

A very useful functionality is that you can store callable delegates in variables :

ExpressionEvaluatorevaluator=newExpressionEvaluator();evaluator.Variables=newDictionary<string,object>(){{"Add",newFunc<int,int,int>((x,y)=>x+y)},{"SayHelloTo",newAction<string>(name=>Console.WriteLine($"Hello{name} !!!"))},};
Add(5, 9)14SayHelloTo("John")Hello John !!!{null}

SubExpression variable

From version 1.4.9.0 you can setSubExpression variables that are evaluate as an expression when they are met.

Live examples here

ExpressionEvaluatorevaluator=newExpressionEvaluator();evaluator.Variables["a"]=1;evaluator.Variables["b"]=2;evaluator.Variables["c"]=newSubExpression("a+b");evaluator.Variables["d"]=newSubExpression("c+3");evaluator.Variables["e"]="c+3";
a1b2c3d6d-a5ec+3

Context object

From version 1.4.6.0, in addition of theVariables dictionary, you can also provide aContext object from which all public properties, fields and methods are directly available.

Live example here

publicclassPerson{publicstringname;publicstringLastName{get;set;}publicDateTimeBirthDate{get;set;}publicintGetTheAgeIfTodayIs(DateTimedate){varage=date.Year-BirthDate.Year;if(BirthDate.Date>date.AddYears(-age))age--;returnage;}}// ...evaluator.Context=newPerson(){name="John",LastName="Smith",BirthDate=newDateTime(1985,09,11)};
name + " " + LastNameJohn SmithGetTheAgeIfTodayIs(new DateTime(2016, 5, 14))30

Standard functions

The following functions are internally defined. (Most of these areSystem.Math Methods directly accessible)

NameDescriptionExampleResult
Abs(double number)Return a double that is the absolute value of numberAbs(-3.2d)3.2d
Acos(double d)Return a double value that is the angle in radian whose d is the cosine
d must be betwteen -1 and 1
Acos(-0.5d)2.0943951023032d
Array(object obj1, object obj2 ,...)Return a array (System.Object[]) of all given argumentsArray(1, "Hello", true)new object[]{1, "Hello", true}
ArrayOfType(Type typeOfTheArray, object obj1, object oj2, ...)Return a array of the specified typeArrayOfType(typeof(char), ',',';')new char[]{',', ';'}
Asin(double d)Return a double value that is the angle in radian whose d is the sine
d must be betwteen -1 and 1
Asin(-0.2d)0.304692654015398d
Atan(double d)Return a double value that is the angle in radian whose d is the tangentAtan(2.1)1.1263771168938d
Atan2(double x, double y)Return a double value that is the angle in radian whose the tangente is the quotient of x and y
Atan2(2.1d, 3.4d)0.553294325322293d
Avg(double nb1, double nb2 ,...)Return a double value that is the average value of all given argumentsAvg(1, 2.5, -4, 6.2)1.425d
Ceiling(double a)Return a double value that is the smallest integer greater than or equal to the specified number.Ceiling(4.23d)5d
Cos(double angle)Return a double value that is the cosine of the specified angle in radianCos(2 * Pi)1d
Cosh(double angle)Return a double value that is the hyperbolic cosine of the specified angle in radianCosh(2d)3.76219569108363d
Evaluate(string expression)Return the result of the evaluation of the given expression. You can disable it withOptionEvaluateFunctionActiveEvaluate("1+2")3d
Exp(double d)Return a double value that is e raised to the specified d powerExp(3d)20.0855369231877d
Floor(double d)Return a double value that is the largest integer less than or equal to the specified d argumentFloor(4.23d)4d
IEEERemainder(double x, double y)Return a double value that is the remainder resulting from the division of x by yIEEERemainder(9, 8)1d
in(object valueToFind, object obj1, object obj2...)Return a boolean value that indicate if the first argument is found in the other argumentsin(8, 4, 2, 8)true
List(object obj1, object obj2 ,...)Return a List (System.Collections.Generic.List) of all given argumentsList(1, "Hello", true)new List<object>(){1, "Hello", true}
ListOfType(Type typeOfTheList, object obj1, object oj2, ...)Return a List of the specified typeListOfType(typeof(string), "Text1","Text2")new List<string>{"Text1", "Text2"}
Log(double a, double base)Return a double value that is the logarithm of a in the specified baseLog(64d, 2d)6d
Log10(double a)Return a double value that is the base 10 logarithm of a specified aLog10(1000d)3d
Max(double nb1, double nb2 ,...)Return a double value that is the maximum value of all given argumentsMax(1d, 2.5d, -4d)2.5d
Min(double nb1, double nb2 ,...)Return a double value that is the minimum value of all given argumentsMin(1d, 2.5d, -4d)-4d
new(TypeOrClass, constructorArg1, constructorArg2 ...)Create an instance of the specified class as first argument and return it. A optional list of additional arguments can be passed as constructor argumentsnew(Random).next(0,10)5d // or a random value between 1 and 9
Pow(double x, double y)Return a double value that is x elevate to the power yPow(2,4)16d
Round(double d, (optional) int digits, (optional)MidpointRounding mode)Rounds d to the nearest integer or specified number of decimal places.Round(2.432,1)2.4d
ScriptEvaluate(string script)Return the result of the evaluation of the given script. You can disable it withOptionScriptEvaluateFunctionActiveScriptEvaluate("value = 1+2;\r\nif(value > 2)\r\nreturn \"OK\";\r\nelse\r\nreturn \"NOK\";")"OK"
Sign(double d)Return 1,-1 or 0 indicating the sign of dSign(-12)-1d
Sin(double angle)Return a double value that is the sine of the specified angle in radianSin(Pi/2)1d
Sinh(double angle)Return a double value that is the hyperbolic sine of the specified angle in radianSinh(2d)3.62686040784702d
Sqrt(double d)Return a double value that is the square root of the specified d valueSqrt(4d)2d
Tan(double angle)Return a double value that is the tangent of the specified angle in radianTan(Pi / 4)1d
Tanh(double angle)Return a double value that is the hyperbolic tangent of the specified angle in radianTanh(2d)0.964027580075817d
Truncate(double d)Return a double value that is the integer part of the specified d valueTruncate(2.45d)2d

Remark : The old if function (NCalc style) has been removed. This to avoid conflicts with the new if, else if, else keywords in script mode. To do something similar on a expression level use the conditional operator( ? : ) instead.

On the fly variables and functions evaluation

In addition to custom variables, you can add variables and/or functions "on the fly" during evaluation.
To do so, 4 C# events are provided. They are fired at evaluation time.

2 events are fired before all evaluations of variables, fields, properties and functions and methods.These two events can be canceled so no further evaluations are done. They are always fired

2 events are fired after all "standard" evaluation of variables, fields, properties and functions and methods.These two events are only fired if no others evaluations succeed.It avoid conflicts but it has also some performance drawback

Before version 1.4.0.0 it had only 2 events (EvaluateVariable and EvaluateFunction) evaluated before but not cancelable

Remark : Can be use to define or redefine on object instances methods or properties

Live example here

ExpressionEvaluatorevaluator=newExpressionEvaluator();// always evaluated before other var and func evaluationsevaluator.PreEvaluateVariable+=Evaluator_PreEvaluateVariable;evaluator.PreEvaluateFunction+=Evaluator_PreEvaluateFunction;// evaluated if no existing var or func existsevaluator.EvaluateVariable+=Evaluator_EvaluateVariable;evaluator.EvaluateFunction+=Evaluator_EvaluateFunction;//...privatestaticvoidEvaluator_PreEvaluateVariable(objectsender,VariablePreEvaluationEventArge){if(e.Name.Equals("myvar1")){e.Value=5;}elseif(e.Name.StartsWith("P")){e.CancelEvaluation=true;}}privatestaticvoidEvaluator_PreEvaluateFunction(objectsender,FunctionPreEvaluationEventArge){if(e.Name.Equals("Test")&&e.Args.Count==1){e.Value=$"It is a test for{e.EvaluateArg(0)}";}elseif(e.Name.StartsWith("A")){e.CancelEvaluation=true;}}privatestaticvoidEvaluator_EvaluateVariable(objectsender,VariableEvaluationEventArge){if(e.Name.ToLower().Equals("myvar2")){e.Value=8;}elseif(e.Name.Equals("MultipliedBy2")&&e.ThisisintintValue){e.Value=intValue*2;}elseif(e.Name.Equals("GenericAssembly")&&e.HasGenericTypes){// e.EvaluateGenericTypes() return a Type[]e.Value=e.EvaluateGenericTypes()[0].Assembly.GetName().Name;}}privatestaticvoidEvaluator_EvaluateFunction(objectsender,FunctionEvaluationEventArge){if(e.Name.ToLower().Equals("sayhello")&&e.Args.Count==1){e.Value=$"Hello{e.EvaluateArg(0)}";}elseif(e.Name.Equals("Add")&&e.ThisisintintValue){e.Value=intValue+(int)e.EvaluateArg(0);}elseif(e.Name.Equals("GenericNamespace")&&e.HasGenericTypes){// e.EvaluateGenericTypes() return a Type[]e.Value=e.EvaluateGenericTypes()[0].Namespace;}}
myvar1 + 27Pithrow an exception (Pi not found)Test(5)It is a test for 5Abs(-3)throw an exception (Abs not found)myVar2 + 210SayHello("Bob")Hello Bob3.MultipliedBy263.Add(2)5GenericNamespace<List<string>>()System.Collections.GenericGenericAssembly<string>mscorlib

Extension methods

To use extension methods ExpressionEvaluator need to know which classes implements extension methods.It can be done like this :

Live example here

publicstaticclassStringExtendedMethods{publicstaticstringAddExtended(thisstringstr){returnstr+" extended";}}// ...ExpressionEvaluatorevaluator=newExpressionEvaluator(newDictionary<string,object>(){{"x","Test"}});evaluator.StaticTypesForExtensionsMethods.Add(typeof(StringExtendedMethods));
x.AddExtended()Test extended

Remark :
ExpressionEvaluator do not find extension methods by itself because depending on the size of your assembly it can be very slow.But if you want, you can use the following code snippet one time somewhere in an "init" place in your code

usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Reflection;usingSystem.Runtime.CompilerServices;// ...foreach(AssemblyassemblyinAppDomain.CurrentDomain.GetAssemblies()){foreach(Typetypeinassembly.GetTypes()){if(type.IsSealed&&!type.IsGenericType&&!type.IsNested&&type.GetMethods(BindingFlags.Static|BindingFlags.Public|BindingFlags.NonPublic).ToList().Any(method=>method.IsDefined(typeof(ExtensionAttribute),false))){evaluator.StaticTypesForExtensionsMethods.Add(type);}}}

Remark :
By default theStaticTypesForExtensionsMethods List containstypeof(Enumerable) to allow a bunch of Linq stuff

Go fluid with a simple methods prefixing convention

When using single expression evaluation.There are cases where we need to use void methods in a fluid syntax manner.

You only need to prefix the method name with "Fluid" or "Fluent"

Live example here

// Example Add on ListList("hello","bye").FluidAdd("test").Count3List("hello","bye").Select(x=>x.ToUpper()).ToList().FluentAdd("test")[0]HELLOList("hello","bye").Select(x=>x.ToUpper()).ToList().FluentAdd("test")[1]BYEList("hello","bye").Select(x=>x.ToUpper()).ToList().FluentAdd("test")[2]testList("hello","bye").Select(x=>x.ToUpper()).ToList().FluentAdd("test").FluidForEach(t=>Console.WriteLine(t)).CountHELLOBYEtest3

If needed this fonctionality can be disabled with :

evaluator.OptionFluidPrefixingActive = false;

Declare and init variables in scripts

In scripts you can declare and use variables.

The way to declare a variable from a script has evolved according of the version of ExpressionEvaluator you use.

An assignation of a variable that do not exists create it automatically. (Can contains any type)
Before version 1.4.0.0 of ExpressionEvaluator it was the only way to declare a variable.
From version 1.4.0.0 you can optionally use the keyword "var". (Can contains any type)
From version 1.4.3.0 you can declare strongly typed variable. (It limit the type that can contain a variable)or optionally use the keyword "dynamic".

// Only supported from version 1.4.3.0intx=2;stringtext="hello";List<string>myList=newList<string>();for(inti=0;i<10;i++)...// If you have an older version. Write this instead :// Still available (for old script compatibility)x=2;text="hello";myList=newList<string>();for(i=0;i<10;i++)...// From version 1.4.0.0 you can also write// Still available (for old script compatibility)var x=2;vartext="hello";varmyList=newList<string>();for(vari=0;i<10;i++)

Remark
All variables are injected in theevaluator.Variables dictionnary.
For strongly typed variable you can only define one time a variable with a specific name.
Warning if you use the same evaluator instance multiple times to callevaluator.ScriptEvaluate(script);with a script that declare strongly typed variables you will have an exception the second time.

Here is a small easy snippet of code to call between your calls ofevaluator.ScriptEvaluate(script); to manage this specific case :

// This code remove all strongly typed variables of the Variable dictionnary.evaluator.Variables.ToList().FindAll(kvp=>kvp.ValueisStronglyTypedVariable).ForEach(kvp=>evaluator.Variables.Remove(kvp.Key));

Simulate function and methods declaration with lambda and multiline lambda

As lambda can be stored in variable and can be multiline in scripts you can use them to simulate function declaration.

--------------------------------------------Add = (x, y) => x+y;Add(3, 2);---------------- Result --------------------5--------------------------------------------SayHelloTo = (name) =>{    hello = "Hye";    return $"{hello} {name}";};SayHelloTo("Joe");---------------- Result --------------------Hye Joe

Remark
You can also assign a lambda to aExpandoObject and so call it as it was a method of thisExpandoObject.

Table Of Content

Clone this wiki locally

[8]ページ先頭

©2009-2025 Movatter.jp