GithubHelp home page GithubHelp logo

zzzprojects / eval-expression.net Goto Github PK

View Code? Open in Web Editor NEW
438.0 30.0 85.0 926 KB

C# Eval Expression | Evaluate, Compile, and Execute C# code and expression at runtime.

Home Page: https://eval-expression.net/

License: Other

C# 100.00%
eval-expression eval evaluation evaluator csharp dotnet

eval-expression.net's Introduction

What's Eval Expression.NET?

Eval Expression.NET improves performance dramatically to access public and private methods, field, property value, or create object instances overusing C# reflection.

It allows you to evaluate, Compile and Execute dynamic C# code and expression at runtime.

From simple C# math expression...

int result = Eval.Execute<int>("X + Y", new { X = 1, Y = 2});

To complex code to parse.

int result = Eval.Execute<int>(@"
	var list = new List<int>() { 1, 2, 3, 4, 5 };
	var filter = list.Where(x => x < 4);
	return filter.Sum(x => x);");

Download

download

PM> Install-Package Z.Expressions.Eval

* PRO Version unlocked for the current month

Eval.Execute

Evaluate and execute the code or expression.

Support:

Anonymous Class

// using Z.Expressions; // Don't forget to include this.
int result = Eval.Execute<int>("X + Y", new { X = 1, Y = 2});

Argument Position

// using Z.Expressions; // Don't forget to include this.
int result = Eval.Execute<int>("{0} + {1}", 1, 2);

Class Member

// using Z.Expressions; // Don't forget to include this.
dynamic expandoObject = new ExpandoObject();
expandoObject.X = 1;
expandoObject.Y = 2;
int result = Eval.Execute<int>("X + Y", expandoObject);

Extension Methods

// using Z.Expressions; // Don't forget to include this.
string s = "X + Y";
int result = s.Execute<int>(new { X = 1, Y = 2 });

Learn more

Eval.Compile

Compile the code or expression and return a delegate.

Support:

Custom Delegate

// using Z.Expressions; // Don't forget to include this.
var compiled = Eval.Compile<Func<int, int, int>>("X + Y", "X", "Y");
foreach(var item in list)
{
	int result = compiled(item.Value1, item.Value2);
}

Extension Methods

// using Z.Expressions; // Don't forget to include this.
string s = "X + Y";
var compiled = s.Compile<Func<int, int, int>>("X", "Y");
foreach(var item in list)
{
	int result = compiled(item.Value1, item.Value2);
}

Learn more

What's supported?

Eval Expression.NET supports all C# Syntax:

You can even access C# 6.0 features even if you are using C# 4.0.

  • string interpolation
  • typename
  • null conditional member access

PRO

Every month, a new monthly trial of the PRO Version is available to let you evaluate all its features without limitations.

Features PRO Version
Maximum Characters Unlimited
Commercial License Yes
Royalty-Free Yes
Support & Upgrades (1 year) Yes
Learn more about the PRO Version
  • Starting from version 2.x, there is no longer a free limited version.
  • LINQ extension method is free with EF Classic - Community

Contribute

The best way to contribute is by spreading the word about the library:

  • Blog it
  • Comment it
  • Star it
  • Share it

A HUGE THANKS for your help.

More Projects

To view all our free and paid projects, visit our website ZZZ Projects.

eval-expression.net's People

Contributors

jonathanmagnan avatar lempireqc avatar mariloutb avatar stgelaisalex avatar waqasm78 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

eval-expression.net's Issues

Problems with function overloads

I have the following code in my functionscope that used to work with the free version of your library. After upgrading to the paid version it no longer works.

The problem is that I use function overloading and so these two Max functions will not be detected when compiling the expression.

   public double Max(double var1, double var2, bool ignoreNaNValues) 

   public double Max(double var1, double var2, double var3)

This is a major problem cause we have lots of customers where the expressions have been used and I suddenly have to break compatibility if I want this to work.

Enum variable with the same name as its type gives null reference exception

I have a problem with naming enums with the same name as its type, The code below runs well as long as you don't have the variable SomeEnum. I put the comment on which line should be commented.

    public enum SomeEnum
    {
        A, B, C, D, E
    }


    public class Entity
    {
        // Commenting Variable SomeEnum will get rid of the runtime error
        public SomeEnum SomeEnum;
        public SomeEnum TheEnum;

        public Entity(SomeEnum someEnum)
        {
            TheEnum = someEnum;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var evalContext = new EvalContext();
            evalContext.BindingFlags = BindingFlags.IgnoreCase | evalContext.BindingFlags;

            evalContext.RegisterType(typeof(Entity));
            evalContext.RegisterType(typeof(SomeEnum));

            var hasSomeEnumA = evalContext.Compile<Func<Entity, bool>>("entity?.TheEnum == SomeEnum.A", "entity");

            var enumValues = Enum.GetValues(typeof(SomeEnum)).Cast<SomeEnum>();
            var entities = enumValues.Select(anEnum => new Entity(anEnum)).ToList();

            foreach (var entity in entities)
            {
                Console.WriteLine(hasSomeEnumA(entity));
            }
        }
    }


Here's the error:

Unhandled Exception: System.NullReferenceException: Object reference not set to an instance of an object.
   at �.�.�(ExpressionScope , � , Expression , Expression , Func`3 )
   at �.�.�(ExpressionScope , � , Func`3 )
   at Z.Expressions.CodeCompiler.CSharp.Compiler.�(ExpressionScope �, � �, Expression �, Boolean �)
   at Z.Expressions.CodeCompiler.CSharp.Compiler.�(ExpressionScope �, � �, Expression �, Boolean �)
   at Z.Expressions.CodeCompiler.CSharp.Compiler.�(ExpressionScope �, � �, Expression �, Boolean �)
   at �.�.�(Type , ExpressionScope , � )
   at Z.Expressions.EvalCompiler.Compile[TDelegate](EvalContext context, String code, IDictionary`2 parameterTypes, Type resultType, EvalCompilerParameterKind parameterKind, Boolean forceFirstParameterProperty)
   at Z.Expressions.EvalContext.Compile[TDelegate](String code, String[] parameterNames)
   at ConsoleApp4.Program.Main(String[] args) in C:\Projects\ConsoleApp4\ConsoleApp4\Program.cs:line 42

Question regarding best approach to shared text-based code features

Hi Johnathan,
In one of my applications I use the Chrome ScriptV8 engine to provide powerful evaluation and scripting, so I'm looking at the feasibility of replacing it with this library.
One feature is that because the ScriptV8's context is shared between many calls, when the 'Engine' is set up I can execute some predefined javascript function definitions, which the user has access to in the macros and conditions they define.
For example, they might create a 'shared' library of javascript functions, and in each guard condition or evaluation process they can call those functions.
In Eval-Expression we can obviously include a type or library, but normally only if it's been compiled into a DLL.
What would be the best way to define a class in a string, and efficiently make that available for multiple calls in the current context?
For example, I might have (just making this up)

public class Data {
  private DBconnection db;
  public Data(DBconnection db)
 {
     _db = db;
 }
  User = (int uid, string dataitem, object fallback = null) => db.FetchUser(uid).GetData(dataitem);
}

This code is stored as a string, not compiled. Is there a way to have this code executed and the type registered in a context to it's always seen by the Eval ?

eval error

I intended this example to be equivalent to an example in a previous report, but it doesn't work, and I don't understand the error message:

Run-time exception (line 23): Oops! No applicable member has been found for the expression. The error occurred for expression "addInput" at position 7 near "addInput(2);
      addInp".

Bug: full Namespace in method

Hi

i got error this code:

    class Program
    {
        public static void test(Type type)
        {
        }

        static void Main(string[] args)
        {
            var context = new EvalContext();
            context.RegisterType(typeof(System.Collections.Generic.Dictionary<, >));
            context.RegisterType(typeof(System.Collections.Generic.List<>));
            context.RegisterType(typeof(Program));
            context.RegisterStaticMember(typeof(Program));
            context.RegisterType(typeof(string));
            var lst = typeof(System.Collections.Generic.Dictionary<System.String, System.String>);
            //Error Line:
            var xx2 = context.Compile<Func<System.Collections.Generic.List<System.String>, object>>(@"
                Program.test(typeof(System.Collections.Generic.List<System.String>));
                return null;", "input");
      }
}

SelectDynamic.Distinct with anonymous type doesn't work as intended

I am trying to use anonymous types in selectdynamic so that I can use .Distinct() for multiple field/column/member. But it seems there is an anonymous type mismatch between the anonymous type created with and without eval context.

If this is an incorrect way of using it, do you have a different way of approaching this? In the real case, Entity will be a large class with numerous members. And the user will input the names of the members to query from.

It is also important for me to be able to grab the values from the result with anonymous type afterwards.

Thank you.

System.InvalidCastException : Unable to cast object of type '<>f__AnonymousType0`2[System.Int32,System.String]' to type '<>f__AnonymousType1`2[System.Int32,System.String]'.
   at System.Linq.Enumerable.<CastIterator>d__94`1.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at CEM.Crunch.Testing.CastingExtension.CastToType[T](IEnumerable`1 item, T exampleItem) in C:\Projects\CEM.Crunch4Beta\CEM.Crunch.Testing\Sandbox.cs:line 93
   at CEM.Crunch.Testing.Sandbox.Something() in C:\Projects\CEM.Crunch4Beta\CEM.Crunch.Testing\Sandbox.cs:line 82
public class Entity
    {
        public int i;
        public string s;

        public Entity(int i, string s)
        {
            this.i = i;
            this.s = s;
        }
    }
            var source = new List<Entity>()
            {
                new Entity(0,""),
                new Entity(1,"a"),
                new Entity(1,"a"),
                new Entity(1,"ab"),
            };

            var list = source
                .SelectDynamic(entity => "new { A = entity.i, B = entity.s }") // prototype of anonymous type
                .Distinct()
                .ToList();

            var castedList = list.Distinct().CastToType(new { A = 0, B = "" }).ToList();

            Console.Write(list.Count);
            Console.Write(castedList.Count);
    public static class CastingExtension
    {
        public static List<T> CastToType<T>(this IEnumerable<object> item, T exampleItem)
        {
            return item.Cast<T>().ToList();
        }
    }

Exception on adding license

Sometimes but not always we get an exception on adding the license when executing our unit tests.

System.NullReferenceException : Object reference not set to an instance of an object.
   at Z.Expressions.CompilerManager.?.?(Tuple`2 ?)
   at System.Collections.Generic.List`1.FindIndex(Int32 startIndex, Int32 count, Predicate`1 match)
   at Z.Expressions.CompilerManager.AddLicense(String licenseName, String licenseKey)

The test are all executed in parallel so it could be possible that the AddLicense method is executed multiple times.

Our code in the a base class looks like this:

if (!EvalManager.ValidateLicense()) {
    EvalManager.AddLicense("xxx", "xxx");
}

No applicable member has been found for the expression in Enumerable

When I execute this code:

    static void Main(string[] args)
    {
        var eval = new EvalContext();
        eval.RegisterDomainAssemblies();

        const string test = @"var list = new List<Int32>();
list.Add(2);
list.Add(1);
list = Enumerable.OrderBy(list, m => m).ToList();
return list;
";
        var testList = Test();
        var invoiceAdd = eval.Execute<List<String>>(test);
    }

    private static IList<Int32> Test()
    {
        var list = new List<Int32>();
        list.Add(2);
        list.Add(1);
        list = Enumerable.OrderBy(list, m => m).ToList();
        return list;
    }

I get the following errors:
'Oops! No applicable member has been found for the expression.'

string.Left method

I downloaded Eval-Expression.NET and am trying it out.

The following command works and returns "Lynn":

string result4 = Eval.Execute("String.Copy("Lynn")");

This command errors out.

string result5 = Eval.Execute("String.Copy("Lynn").Left(1)");

Should I be able to do something like I am trying to do? I am trying to understand the capabilities of this library by trying different scenarios.

Thanks.

Strange memory of previous values...

If I evaluate the expression:
new { a=1, b="B"};
I would expect to subsequently evaluate the expression
new { a="1", b="B"};
But doing this raises the error:
Argument type 'System.String' does not match the corresponding member type 'System.Int32'
because it's somehow remembering the nested anonymous object type's a variable is an integer.
Is this a bug, or is there a way to prevent this context caching or 'remembering' these data types?

Null property value causes eval exception

Following code works:

dynamic expandoObject = new ExpandoObject();
expandoObject.Property1 = true;
if (Eval.Execute<bool>(@"Property1 == true", expandoObject))
{
Console.WriteLine(@"Property1 == true");
}

But the following (with an irrelevant null property) will just error out:

dynamic expandoObject = new ExpandoObject();
expandoObject.Property1 = true;
expandoObject.Property2 = null;
if (Eval.Execute<bool>(@"Property1 == true", expandoObject))
{
Console.WriteLine(@"Property1 == true");
'}`

Is this something you can fix?
Thank you.

The parser should give error messages at least as good as from the C# compiler.

This is really unusable:

Run-time exception (line 116): Object reference not set to an instance of an object.

Stack Trace:

[System.NullReferenceException: Object reference not set to an instance of an object.]
at .(ExpressionScope , SyntaxNode )
at .(ExpressionScope , SyntaxNode , Expression , Boolean )
at .(ExpressionScope , SyntaxNode , Expression , Boolean )
at .(ExpressionScope , SyntaxNode , Expression , Boolean )
at Z.Expressions.CodeCompiler.CSharp.ExpressionParser.ParseSyntax(ExpressionScope scope, SyntaxNode node, Type resultType)
at .[](EvalContext , String , IDictionary2 , Type , EvalCompilerParameterKind , Boolean , Boolean ) at Z.Expressions.Eval.Compile(String code, IDictionary2 parameterTypes)
at Program.evalDemo5() :line 116
at Program.testEval() :line 22
at Program.Main() :line 11

Support of DynamicObject or IDictionary<string, object> as context object

If I run

var values = new ServiceExample2() { { "X", 1 }, { "Y", 2 } };
int result = context.Execute<int>("X + Y", values);

where ServiceExample2 is inherits from Dictionary<string, object> it works as expected. When it implements IDictionary<string, object> or inherits DynamicObject and implements the properties dynamically, it throws NullReferenceException.

Is there some other way how to run on object with has not the properties known at compile time?

Thanks

Bug: generic list full name

hi

use: error
System.Collections.Generic.List<System.Collections.Generic.List<System.String>
use: not error
System.Collections.Generic.List<List<System.String>>

sample:


            var context = new EvalContext();
            context.RegisterType(typeof(System.Collections.Generic.List<>));
            context.RegisterType(typeof(string));

            //Not Error
            var xx2 = context.Compile<Func<System.Collections.Generic.List<System.String>, object>>(@"
                var lst = new System.Collections.Generic.List<List<System.String>>();
                return lst;", "reader");

            //Error
            var xx = context.Compile<Func<System.Collections.Generic.List<System.String>, object>>(@"
                var lst = new System.Collections.Generic.List<System.Collections.Generic.List<System.String>>();
                return lst;", "reader");

error running the ExpandoObject example

I am trying to get the examples running from your website. I have been successful getting 3 of 4 working. The only one not working is the ExpandoObject example.

Here is my code:

        // using Z.Expressions; // Don't forget to include this.
        int result1 = Eval.Execute<int>("X + Y", new { X = 1, Y = 2 });
        Console.WriteLine(result1);

        // using Z.Expressions; // Don't forget to include this.
        int result2 = Eval.Execute<int>("{0} + {1}", 1, 2);
        Console.WriteLine(result2);

        // using Z.Expressions; // Don't forget to include this.
        dynamic expandoObject = new ExpandoObject();
        expandoObject.X = 1;
        expandoObject.Y = 2;
        int result3 = Eval.Execute<int>("X + Y", expandoObject);
        Console.WriteLine(result3);

        // using Z.Expressions; // Don't forget to include this.
        string s = "X + Y";
        int result4 = s.Execute<int>(new { X = 1, Y = 2 });
        Console.WriteLine(result4);

        Console.ReadKey();

Here is my error:

-System.InvalidOperationException: 'The binary operator Add is not defined for the types 'System.Object' and 'System.Object'.'

I am using the evaluation version 2.4.3

System.StackOverflowException

First of all, awesome library!!

I'm getting StackOverflow at i = 212;

string expression = "a * 5 - b / 2";
            for (int i = 0; i < 1000; i++)
            {
                expression = expression + " + a - b";

                decimal xxx = expression.Execute<decimal>(new
                {
                    a = 2,
                    b = 4
                });
            }

HasValue and also null values

My comments and questions are in the code below:

        DateTime? dateTimeA;

        // this works
        dateTimeA = new DateTime(2017, 1, 1);
        string result1 = Eval.Execute<string>("{0}.AddDays(1).ToString()", dateTimeA);
        Console.WriteLine(result1);

        // this is what I want to do ...
        dateTimeA = new DateTime(2017, 1, 1);
        int result2 = dateTimeA.HasValue ? 1 : 0;
        Console.WriteLine(result2);

        // this is also what I want to do, but ...
        dateTimeA = null;
        int result3 = dateTimeA.HasValue ? 1 : 0;
        Console.WriteLine(result3);

        // I can't get it this to work
        dateTimeA = new DateTime(2017, 1, 1);
        int result4 = Eval.Execute<int>("{0}.HasValue ? 1 : 0", dateTimeA);
        Console.WriteLine(result4);

        // And I can't get it this to work
        dateTimeA = null;
        int result5 = Eval.Execute<int>("{0}.HasValue ? 1 : 0", dateTimeA);
        Console.WriteLine(result5);

        Console.ReadKey();

Limited exception information ... stuck ...

Hey guys,

I got everything running under .Net 4.x and then it turned out for M$ reasons the only way everything was going to work the way I wanted was to upgrade to .Net Core 2.2 so here I am.

This code works perfectly under .Net 4.x but for some reason under .Net Core I can't seem to get it to behave and the exception is giving me literally nothing.

So here's the code ....

var script = "((Core.Objects.Workflow.Activities.DebugActivity)activity).Message = ((Core.Objects.Workflow.Activities.Start<System.Object>)activity.Previous[0]).Data.Message;";
var result = assignContext.Compile<Action<Activity>>(script, "activity");

At runtime I have a collection of Activities that derive from this base type ...

   public abstract class Activity
    {
        public string Ref { get; set; }
        public Activity[] Previous { get; set; }
        public Activity[] Next { get; set; }
        public Action<Activity> AssignValues { get; set; } 
        ....
    }

... I have a "Flow" object that contains a collection of activities and a collection of "Links" which contain the expressions that I need to compile.

After constructing each activity as it's concrete type and assigning each of the previous and next arrays shown in the base type above I run the code that's failing in an attempt to build the AssignValues Action for each activity that has link information.

The exception information I'm getting looks like this ...

Message

Value cannot be null.

Stack trace

   at System.RuntimeType.MakeGenericType(Type[] instantiation)
   at .(ExpressionScope , SyntaxNode , StringBuilder , Int32& , Boolean )
   at .(ExpressionScope , SyntaxNode , StringBuilder , Int32& , Boolean )
   at .(ExpressionScope , SyntaxNode , Boolean )
   at .(ExpressionScope , SyntaxNode , Expression , Boolean )
   at .(ExpressionScope , SyntaxNode , Expression , Boolean )
   at .(ExpressionScope , SyntaxNode , Expression , Boolean )
   at .(ExpressionScope , SyntaxNode , Expression , Boolean )
   at .(ExpressionScope , SyntaxNode )
   at .(ExpressionScope , SyntaxNode , Expression , Boolean )
   at .(ExpressionScope , SyntaxNode , Expression , Boolean )
   at .(ExpressionScope , SyntaxNode , Expression , Boolean )
   at Z.Expressions.CodeCompiler.CSharp.ExpressionParser.ParseSyntax(ExpressionScope scope, SyntaxNode node, Type resultType)
   at .[](EvalContext , String , IDictionary`2 , Type , EvalCompilerParameterKind , Boolean , Boolean )
   at Z.Expressions.EvalContext.Compile[TDelegate](String code, String[] parameterNames)
   at Workflow.FlowInstance.BuildAssign[T](T activity, Flow flow) in D:\Core Prototype\Everything\Workflow\FlowInstance.cs:line 247

Is there any obvious reason that this would fail as this seems pretty straightforward for the code I have?

Question: "sys:bool"

Hey there,

Pretty impressed with this library. I am running into a problem, however. It seems as if expressions such as sys:bool resolve to the bool type. Which is pretty cool. Unfortunately this conflicts with how I am using the same tokens. :) For some context, I am using Eval as such:

public object Get(string parameter)
{
	try
	{
		var invoke = Eval.Compile(parameter).Invoke();
		return invoke;
	}
	catch (Exception)
	{
		return Eval.Compile(parameter.Quoted()).Invoke();
	}
}

If there is an error in parsing, then I wrap it as a string and try again. So, I am expecting sys:bool to fail, at which point I would wrap it in quotes and try again (thereby returning a string).

Is there a way to turn off this magic, by chance?

Mono Support?

If i try to run a Console application with the following statement:
"var func = Z.Expressions.Eval.Compile("1+2");"

I am getting an Exception:

System.TypeInitializationException: The type initializer for 'Z.Expressions.EvalManager' threw an exception. ---> System.TypeLoadException: Could not resolve type with token 010000bb
at Z.Expressions.EvalContext..ctor () [0x0007a] in <30ed86fefe7e4b81af44bca0ad083405>:0
at Z.Expressions.EvalManager..cctor () [0x0000a] in <30ed86fefe7e4b81af44bca0ad083405>:0
--- End of inner exception stack trace ---
at Z.Expressions.Eval.Compile (System.String code) [0x00000] in <30ed86fefe7e4b81af44bca0ad083405>:0
at MDebugConsoleApp5.Program.Main (System.String[] args) [0x00002]

Do you see the possibilities to support Mono?

IQueryable EF Syntax error with select

The below statement is invalid when attempting to select against a sub-item in the query. The object exists using Include(p => p.Contacts) which should allow this syntax in static code.

n.Select(
q => new {
q.Contacts.AddressLine1
}
).ToList();

However, here is the output error I am getting from the above statement.
The entity looks like so

Case
-> Contacts, where contacts are a related table.

The EF query is

Context.Cases.Include(p => p.Contacts);

'Oops! No applicable member has been found for the expression. The error occurred for expression "." at position 1 near ".Select(
q => new {
q.C".'

NullReferenceException

When i try to execute the following code i get a 'Object reference not set to an instance of an object.'

var evalContext = new EvalContext();
evalContext.RegisterDomainAssemblies();
var body = @" new DomainMessage(""UserValidated"",cp?.Messages[""ValidatedUser""]?.Entity,
                                new StateEventInfo(cp?.Actor?.Process?.Id, 
Context.Domain.Events.DomainEventPublished),
                                cp.Actor.Process, cp.Actor.Source)";
var res = evalContext.Compile<Func<IComplexEventParameters, IProcessSystemMessage>>(body, "cp");

The parameter contains dynamic types is that the cause?

Issues with dynamically generated types

Hi @JonathanMagnan ,

I'm back, sorry! :-D

This time I'm having some problems with referencing instance members of a string property, which is declared in a dynamically generated type.

Given a datacontext that has a property named Custom of type dynamic, which is assigned an instance of a dynamically generated class that has a Cluster property of type string, the following expression throws an exception:

bool result = Eval.Execute("Custom.Cluster.Contains("Foo")", datacontext);

Attached is a solution with a minimal repro of what I'm doing, stripped down from my real project.

ExpressionsEvalTests.zip

Best Regards,

-Rodrigo-

Instance context methods are not supported

EvalContext documentation:

Problem: You need to evaluate a dynamic C# code in an instance context.

My example:

public class Custom
{
    public int Add(int a, int b)
    {
        return a + b;
    }
}

new EvalContext().Execute<int>("Add(1, 2)", new Custom()); // exception: No applicable member has been found for the expression.

Please explain more about how it works

Please greatly expand the Documentation. Many things are mysterious. Documentation about how things work would really help.

  • Why do I have to put names for variables in my code into a dictionary, whereas things from certain libraries are just there. Btw, which libraries are included?
  • How do I use the name of one of my classes in a script? For example, I can't say var foo = new Holder(); I had to work around this by making a function that calls new Holder(), making a delegate that points to it, adding the delegate to the dictionary, and calling the delegate in the script.
  • I had to experiment to see how to allow the script code to call a method. And it's not obvious that you can declare a delegate and put that in the dictionary.

See my examples.

Querying dynamic data with generated LINQ queries

Hey @JonathanMagnan,

Here's some more detail on an issue i'm having which relates closely to #44 but I didn't feel right in canabalizing @tomasceleda's issue for my own problem (feel free to close and merge if you think these are the same problem though).

I put together a fiddle (seems to be the best way to hand over a complete "working" sample of the problem ...

https://dotnetfiddle.net/ZZ4V1B

... In the sample you can see that I can "manually execute the query" but I can't dispatch the same code to Eval.Execute() for some reason.

testResult = ... on line 73 of the code sample runs fine.
Given the same code to Eval.Execute() as a string on line 102 it fails with a strange exception I don't understand how to parse.

Please consider supporting the ICustomTypeProvider interface

Hi, I have a use case that doesn't seem to be covered yet by your very nice library.

In my app I have an existing data context which is made of a few dictionaries, because it's dynamic in nature.

I would like to give the user the ability to write conditions based on that data context, but it would be really nice if he/she could write something like Custom.BirthDate.Year > 1980 rather than Custom["BirthDate"].Year > 1980.

So I went ahead and implemented an ICustomTypeProvider in order to populate my object dynamically and have Eval.Execute read it as if it was a regular object, but I get a NullReferenceException.

I guess it would be a matter of checking for the interface and call GetCustomType() instead of GetType() before using the existing reflection algorythm.

Thanks.

Dynamic update Query in EF core

Hello

My requirement is i want to find table which have foreign key of Master table then i want to update foreign key all this table.

Requirement with example

I have i product table. its primary key is PkProductID . its in have foreign key in multipal table. I want to find all the table which have foreign key on productid and update prodductid from other productid inall the table .

Please conform this functionality have in your product ?

Performance Idea

Hi ZZZ,
This isn't a bug report but an idea that I had that I wanted to share with you. Ya'll seem to know the insides of .NET pretty well.

Anyway, I would definitely pay for the ability to convert runtime code into static values. For example, let's say I have this code:

Console.WriteLine(MultAdd(1,3));

[Fold] 
public static void MultAdd(int x, int y){ 
    return x*y+4; 
}

I would like my code to compile, and then, everywhere a [Fold] method is invoked, if all the values are knowable, then actually invoke the function and replace the value. Essentially, the code above would be rewritten into:

Console.WriteLine(7);

Dynamic querying ... RE:#47 (i guess)

Hey Jonathon,

I just yesterday updated to the latest version (2.9.6.0) as I knew today I would be working on this particularly troublesome query (it's brutal not being dynamic to be honest)
I've extracted this small piece of it to help identify the problem.

It seems that Eval is not agreeing with the same raw C# and I wondered if you'd lend some light on the subject.

I've also uploaded the code to dot net fiddle here ... https://dotnetfiddle.net/MbZJjf

Please note, if you copy paste this code in to a new console app project, then add refs to newtonsoft.json and z.expressions.eval from nuget you should be good to go (I checked this to be sure you could get up and running ASAP :)

using System.Text;
using System.Dynamic;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using Newtonsoft.Json;

public class Program
{
    public static void Main()
    {
        // excuse the prep work here, this is an extraction from my code base in it's simplest form
        var doc = XDocument.Parse(TestData.XMLSource);
        var json = BuildCleanJSON(doc);
        dynamic data = JsonConvert.DeserializeObject<ExpandoObject>(json);

        // this is the object we care about, i'm essentially generating "query" below to execute on this object
        dynamic source = new ExpandoObject();
        source.Data = new[] { ((dynamic)data).VPR_DirectData };
        source.Companies = TestData.Companies;

        var query = @"
((IEnumerable<dynamic>)Data)
    .SelectMany((dynamic buyer) => ((IEnumerable<dynamic>)buyer.MASTERDATA)
        .SelectMany((dynamic supplier) => ((IEnumerable<dynamic>)supplier.VENDORITEMS)
            .Select((dynamic item) => new
            {
                BuyerFCSRef = buyer.HEADER.CC_Code,
                BuyerName = buyer.HEADER.CC_DESC,
                Buyer = ((IEnumerable<dynamic>)Companies).FirstOrDefault((dynamic company) => company.HasReference(""FCS"", buyer.HEADER.CC_Code)),
                SupplierFCSRef = supplier.VEND_CODE,
                SupplierName = supplier.VEND_NAME,
                Supplier = ((IEnumerable<dynamic>)Companies).FirstOrDefault((dynamic company) => company.HasReference(""FCS"", supplier.VEND_CODE)),
                FunderFCSRef = supplier.FACTOR,
                ItemRef = item.REFERENCE,
                LineItem = item
            }).ToArray()
        ).ToArray()
    ).ToArray()
    .GroupBy(i => i.ItemRef)
    .Select(group => new { Ref = group.Key, Items = group.ToArray() })
    .ToArray();
";

        // trial run using "native .Net"
        dynamic[] Data = source.Data;
        dynamic[] Companies = source.Companies;

        var result = ((IEnumerable<dynamic>)Data)
            .SelectMany((dynamic buyer) => ((IEnumerable<dynamic>)buyer.MASTERDATA)
                .SelectMany((dynamic supplier) => ((IEnumerable<dynamic>)supplier.VENDORITEMS)
                    .Select((dynamic item) => new
                    {
                        BuyerFCSRef = buyer.HEADER.CC_Code,
                        BuyerName = buyer.HEADER.CC_DESC,
                        Buyer = ((IEnumerable<dynamic>)Companies).FirstOrDefault((dynamic company) => company.HasReference("FCS", buyer.HEADER.CC_Code)),
                        SupplierFCSRef = supplier.VEND_CODE,
                        SupplierName = supplier.VEND_NAME,
                        Supplier = ((IEnumerable<dynamic>)Companies).FirstOrDefault((dynamic company) => company.HasReference("FCS", supplier.VEND_CODE)),
                        FunderFCSRef = supplier.FACTOR,
                        ItemRef = item.REFERENCE,
                        LineItem = item
                    }).ToArray()
                ).ToArray()
            ).ToArray()
            .GroupBy(i => i.ItemRef)
            .Select(group => new { Ref = group.Key, Items = group.ToArray() })
            .ToArray();

        // re-run of the same query using Z.Expressions.Eval 
        // This is where it goes wrong.
        var compilerResult = Z.Expressions.Eval.Execute<dynamic>(query, source);
    }

    public static string BuildCleanJSON(XDocument xDoc)
    {
        var builder = new StringBuilder();
        JsonSerializer.Create().Serialize(new CleanJsonWriter(new StringWriter(builder)), xDoc);
        return builder.ToString();
    }
}

public static class TestData
{
    public static string XMLSource { get; } = @"<?xml version=""1.0"" encoding=""utf-8""?>
<n0:VPR_DirectData xmlns:n0=""http://faurecia.com/sap_ecc/ratool/inr227"" xmlns:prx=""urn:sap.com:proxy:TC1:/1SAI/TAS27C150FBCBD114A88521:740"">
    <FILE_HEADER>
        <FILENAME>FD_FR01_OI_20190128_160827.xml</FILENAME>
    </FILE_HEADER>
    <HEADER CC_Code=""FR01"" CC_DESC=""Faurecia Bloc Avant"" EXT_TYPE=""OI"" EXT_MODE=""C""/>
    <MASTERDATA VEND_CODE=""0000116443"" VEND_NAME=""Valeo Autozubehor"" VATREGNUM=""FR41316014984"" CUSTOMER=""C099000040"" FACTOR=""0000189200"" PAY_TERM=""ZP60"" PAY_TERM_DESC=""50%Z400,50%ZM4M"">
        <VENDORITEMS NUMBER=""PW-001"" FYEAR=""2019"" FI_ITEM=""001"" DOC_TYPE=""RE"" DATE=""20181225"" CURRENCY=""EUR"" POSTING_DATE=""20170620"" REFERENCE=""Ref1"" DEBITCREDIT=""H"" AMOUNT=""900.00"" VAT_AMOUNT=""100.00"" VATREGNUM=""FR41316014984"" DUE_DATE=""20181225"" RELINV_FY=""0000"" RELINV_ITEM=""000"" PAYMENT_TERM=""Z150""/>
        <VENDORITEMS NUMBER=""PW-002"" FYEAR=""2019"" FI_ITEM=""001"" DOC_TYPE=""RE"" DATE=""20181225"" CURRENCY=""EUR"" POSTING_DATE=""20170620"" REFERENCE=""Ref2"" DEBITCREDIT=""H"" AMOUNT=""900.00"" VAT_AMOUNT=""100.00"" VATREGNUM=""FR41316014984"" DUE_DATE=""20181225"" RELINV_FY=""0000"" RELINV_ITEM=""000"" PAYMENT_TERM=""Z150""/>
    </MASTERDATA>
    <MASTERDATA VEND_CODE=""0000116443"" VEND_NAME=""Valeo Autozubehor"" VATREGNUM=""FR41316014984"" CUSTOMER=""C099000040"" FACTOR=""0000189200"" PAY_TERM=""ZP60"" PAY_TERM_DESC=""50%Z400,50%ZM4M"">
        <VENDORITEMS NUMBER=""PW-001"" FYEAR=""2019"" FI_ITEM=""001"" DOC_TYPE=""RE"" DATE=""20181225"" CURRENCY=""EUR"" POSTING_DATE=""20170620"" REFERENCE=""Ref1"" DEBITCREDIT=""H"" AMOUNT=""900.00"" VAT_AMOUNT=""100.00"" VATREGNUM=""FR41316014984"" DUE_DATE=""20181225"" RELINV_FY=""0000"" RELINV_ITEM=""000"" PAYMENT_TERM=""Z150""/>
        <VENDORITEMS NUMBER=""PW-002"" FYEAR=""2019"" FI_ITEM=""001"" DOC_TYPE=""RE"" DATE=""20181225"" CURRENCY=""EUR"" POSTING_DATE=""20170620"" REFERENCE=""Ref2"" DEBITCREDIT=""H"" AMOUNT=""900.00"" VAT_AMOUNT=""100.00"" VATREGNUM=""FR41316014984"" DUE_DATE=""20181225"" RELINV_FY=""0000"" RELINV_ITEM=""000"" PAYMENT_TERM=""Z150""/>
    </MASTERDATA>
</n0:VPR_DirectData>
";

    // MasterData = Supplier Info
    //   vend_code = fcs ref
    //   vatregnum = tax ref
    // Header = Buyer Info
    //   cc_code = FCS reference

    public static Company[] Companies { get; } = new[]
    {
        new Company
        {
            CompanyId = 1,
            CompanyName = "Test Company 1",
            CompanyTaxIdentifiers = new[]
            {
                new CompanyTaxIdentifier { Reference = "FR01", ExternalReferenceSystem = new ExternalReferenceSystem { DisplayName = "FCS" } }
            }
        },
        new Company
        {
            CompanyId = 2,
            CompanyName = "Test Company 2",
            CompanyTaxIdentifiers = new[]
            {
                new CompanyTaxIdentifier { Reference = "0000116443", ExternalReferenceSystem = new ExternalReferenceSystem { DisplayName = "FCS" } }
            }
        },
        new Company
        {
            CompanyId = 3,
            CompanyName = "Test Company 3",
            CompanyTaxIdentifiers = new[]
            {
                new CompanyTaxIdentifier { Reference = "0000189200", ExternalReferenceSystem = new ExternalReferenceSystem { DisplayName = "FCS" } }
            }
        }
    };
}

public class Company
{
    public int CompanyId { get; set; }
    public string CompanyName { get; set; }
    public ICollection<CompanyTaxIdentifier> CompanyTaxIdentifiers { get; set; }

    public bool HasReference(string system, string reference)
    {
        return CompanyTaxIdentifiers?.Any(cti => cti.ExternalReferenceSystem.DisplayName == system && cti.Reference == reference) ?? false;
    }
}

public class CompanyTaxIdentifier
{
    public string Reference { get; set; }
    public ExternalReferenceSystem ExternalReferenceSystem { get; set; }
}

public class ExternalReferenceSystem
{
    public string DisplayName { get; set; }
}

public class CleanJsonWriter : JsonTextWriter
{
    public CleanJsonWriter(TextWriter writer) : base(writer) { }

    public override void WritePropertyName(string name)
    {
        var result = name;
        if (name.StartsWith("@") || name.StartsWith("#"))
            result = name.Substring(1);

        if (result.Contains(":"))
            result = result.Split(":".ToCharArray()).Last();

        base.WritePropertyName(result);
    }
}

Cannot add library to UWP

I want to use the library in a application on Windows IoT on Raspberry PI. But when adding the library using nuget I get the following error:
System.Reflection.Emit.ILGeneration 4.3.0 provides a compile-time reference assembly for System.Reflection.Emit.ILGeneration on UAP,Version=v10.0, but there is no run-time assembly compatible with win10-arm-aot. One or more packages are incompatible with UAP,Version=v10.0 (win10-arm-aot). System.Reflection.Emit.ILGeneration 4.3.0 provides a compile-time reference assembly for System.Reflection.Emit.ILGeneration on UAP,Version=v10.0, but there is no run-time assembly compatible with win10-x64-aot. One or more packages are incompatible with UAP,Version=v10.0 (win10-x64-aot). System.Reflection.Emit.ILGeneration 4.3.0 provides a compile-time reference assembly for System.Reflection.Emit.ILGeneration on UAP,Version=v10.0, but there is no run-time assembly compatible with win10-x86-aot. One or more packages are incompatible with UAP,Version=v10.0 (win10-x86-aot). Package restore failed for 'ProjectName'. Package restore failed. Rolling back package changes for 'ProjectName'.

My project.json is this:
{ "dependencies": { "Microsoft.NETCore.UniversalWindowsPlatform": "5.2.2", }, "frameworks": { "uap10.0": {} }, "runtimes": { "win10-arm": {}, "win10-arm-aot": {}, "win10-x86": {}, "win10-x86-aot": {}, "win10-x64": {}, "win10-x64-aot": {} } }

Do you think this issue can be solved on Z.Expressions.Eval?

"Not" operator parsing problem

Hi guys,

This isn't a big concern, since there are workarounds, but I thought you might be interested.
Given an eval context where I registered this static method:


    public static class MyMethods
    {
        public static bool GiveMeTrue()
        {
            return true;
        }
    }

            var context = new EvalContext {UseCache = false};
            context.RegisterStaticMember(typeof(MyMethods));
            context.RegisterType(typeof(MyMethods));

The following works as expected:

var result = context.Execute("GiveMeTrue()");
Assert.IsTrue(result);

But the following throws a compile error: Oops! The type could not be found.

var result = context.Execute("!GiveMeTrue()");
Assert.IsFalse(result);

Unless I enclose the method invocation in parens:

var result = context.Execute("!(GiveMeTrue())");
Assert.IsFalse(result);

Now, if I write this the error message is differnet, actually more to the point I think:
-Missing left expression for binary keyword or operator "==" at position 14 near "== true"-

var result = context.Execute("!GiveMeTrue() == true");
Assert.IsFalse(result);

Again, by using extra parens the parser get it right.

var result = context.Execute("!(GiveMeTrue()) == true");
Assert.IsFalse(result);

-Rodrigo-

How can i call External dll method?

I want to use my dll method with eval. How can i do this?

Test code is this.

// Test
public class Program
{
	static void Main( string [ ] args )
	{
		string path = @"E:\Temp\test.png";
		Image<Bgr,byte> res = Eval.Execute<Image<Bgr,byte>>(
			@"
				WriteLine( Path );
				return F(Path);
			" , new { Path = path , F = Getimg }
			);

		WriteLine();
	}

	static Func<string,string> Getimg = Path => "Image";
}

Unicode chars are not handled in member names

Hello guys,

I've found that the library thows an exception when it encounters member names containing accented letters, like in the following unit test.

[TestMethod]
public void CanHandleUnicodeMemberNames()
{
    var context = new EvalContext { UseCache = false };
    var code = @"Quantità == 10";
    var dataContext = new {Quantità = 10};
    var result = context.Execute(code, dataContext);
    Assert.IsTrue(result);
}

Given that c# allows for unicode characters in member names I didn't expect this behavior.

Thanks!

Bug: typeof namespace full name

Hi

i got error this code:

           var context = new EvalContext();
            context.RegisterType(typeof(System.Collections.Generic.Dictionary<, >));
            context.RegisterType(typeof(System.Collections.Generic.List<>));

            context.RegisterType(typeof(string));

            var test2 = context.Compile<Func<System.Collections.Generic.List<System.String>, object>>(@"
                var lst = typeof(System.Collections.Generic.List<System.Collections.Generic.List<System.String>>);
                return null;", "input");

brackets mismatch

I just discovered a problem with brackets. Ex.
((1=1) or ((2=2)
the above formula considered as a legit expression and able to evaluate. Can you please fix. Thanks

Issues with ExpandoObject and Static members

Hi,

I'm having a hard time figuring out why I cannot reference String.IsNullOrEmpty(...) and I found that it really depends on the data that is sent in as a parameter! Sometimes the String alias is getting lost.

So I wrote some unit tests to figure out when and why.
It looks like the ExpandoObject is causing the bug, both when it's used as the root data object or as a second-level data object.

In my use case I have a root object that exposes 2 properties, which need to be dynamic.
At the root level we have: System and Custom.
Both of them have different members from time to time, so they need to be either a dictionary or an ExpandoObject. I would prefere the latter because my clients can use a nicer syntax (Custom.Foo.Length instead of Custom["Foo"].Length for example).

I attached my unit tests.

EvalTests.cs.txt

Can you please help me?
I'm using version 2.4.12

Thanks!

Use DateTime values

Hi,

using ExpressionEvaluator.dll Version 2.0.4.0
actually we get DateTimes as a input from our users and would like to perform equality compare and so on.

So how can I declare for the Evaluator that something like '01.01.2017 08:00:00' is a date? Tried allready to use stuff like DateTime.Parse but it did not work (Is there a way to use functions from c# System lib at this version)

regards
saitham

Initializing a list with type T of a complex type not working

When trying to execute the following code:

var test= new ComplexType();

var list = new List<ComplexType>();

ComplexType is just a class in this example.

it fails at the 2nd line with the message: Oops! The type could not be found. Only common type are registered by default. Make sure the type you are using is registered: https://github.com/zzzprojects/Eval-Expression.NET/wiki/EvalContext-Register-&-Unregister

How to debug issues ?

So I hit this issue.
I made the following call ...

var function = Eval.Compile("activity.Foo = activity.Previous[0].Foo", "activity");

... and got this back ...

System.NullReferenceException: Object reference not set to an instance of an object.
   at ?.?(ExpressionScope ?, SyntaxNode ?)
   at ?.?(ExpressionScope ?, SyntaxNode ?, Expression ?, Boolean ?)
   at ?.?(ExpressionScope ?, SyntaxNode ?, Expression ?, Boolean ?)
   at ?.?(ExpressionScope ?, SyntaxNode ?, Expression ?, Boolean ?)
   at Z.Expressions.CodeCompiler.CSharp.ExpressionParser.ParseSyntax(ExpressionScope scope, SyntaxNode node, Type resultType)
   at ?.?[?](EvalContext ?, String ?, IDictionary`2 ?, Type ?, EvalCompilerParameterKind ?, Boolean ?, Boolean ?)
   at Z.Expressions.EvalContext.Compile[TDelegate](String code, String[] parameterNames)
   at Z.Expressions.Eval.Compile[TDelegate](String code, String[] parameterNames)

The next line in the reported exception was the line in my code that made this call.
I'm not sure how I can get a null reference exception when all i did was give it a simple string pair.

Any ideas?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.