zzzprojects / Eval-Expression.NET

C# Eval Expression | Evaluate, Compile, and Execute C# code and expression at runtime.
https://eval-expression.net/
Other
449 stars 86 forks source link

Not Case Sensitive? #95

Closed cesaryuan closed 3 years ago

cesaryuan commented 3 years ago

It seems that the EvalContext is not case sensitive. I test the code below, and it throw errors.

class Test
{
    public static void add()
    {

    }

    public static void Add()
    {

    }
}

static void Main(string[] args)
{
    var context = new EvalContext();
    context.RegisterType(typeof(Test));
    context.Execute("Test.add()");
}

Errors

Z.Expressions.Compiler.Shared.EvalException
  HResult=0x80131500
  Message=Oops! Ambiguous match found for: 'add'. The error occurred for expression "." at position 4 near ".add()".
  Source=Z.Expressions.Eval
  StackTrace:
   at .(ExpressionScope , Expression , Type , String , List`1 , Boolean , List`1 , SyntaxNode , Expression& )
   at .(ExpressionScope , SyntaxNode , Type , Expression , List`1 )
   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 , ExpressionScope , String , Boolean , Boolean )
   at .[](EvalContext , String , IDictionary`2 , Type , EvalCompilerParameterKind , Boolean , Boolean , Boolean )
   at Z.Expressions.EvalContext.Execute[TResult](String code)
   at SomeTest.Program.Main(String[] args) in E:\Desktop\Program\C#\SomeTest\Program.cs:line 63

  此异常最初是在此调用堆栈中引发的: 
    [外部代码]
    SomeTest.Program.Main(string[]) (位于 Program.cs 中)
JonathanMagnan commented 3 years ago

Hello @cesaryuan ,

You are right, by default our library is case insensitive.

You can change this behavior using the following options:

// default is BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.IgnoreCase
context.BindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;

I must admit this is not obvious for people who don't have the source code to disable this case sensitivity, so I will ask my developer to add a new option named IsCaseSensitive to make it more obvious.

Best Regards,

Jon

JonathanMagnan commented 3 years ago

Hello @cesaryuan ,

The v4.0.31 has been released.

We added a new option named IsCaseSensitive which will automatically adjust the BindingFlags.

For backward compatibility reason, we must keep the IsCaseSensitive = false by default. But you can now easily modify it.

Let me know if it works as expected.

Best Regards,

Jon

cesaryuan commented 3 years ago

@JonathanMagnan Thanks! This is already very convenient.

stonstad commented 3 years ago

I have case sensitivity set to false but I get errors when I refer to properties with different case, i.e. Foo.Bar and Foo.bar.

''System.Dynamic.ExpandoObject' does not contain a definition for 'bar''.

Is there a separate setting or way to work through this to achieve case insensitivity?

stonstad commented 3 years ago

To clarify, I am passing in a object parameters to Eval(), and it is properties of these parameters that I am hoping to match without case sensitivity.

JonathanMagnan commented 3 years ago

Hello @stonstad ,

Could you confirm that you are doing something similar to this:

var context = new EvalContext();
context.IsCaseSensitive = false;

dynamic expando = new ExpandoObject();
expando.x = 1;
expando.y = 2;
var r1 = Eval.Execute("x + Y", expand);

I will ask my developer to look at this. I believe the "IsCaseSensitive" should also apply here. However, I'm not sure if that's possible, the problem is that we need to compile it and the ExpandoObject have no existing properties on the compilation. From an expando to another, it could be lowercase or uppercase for example.

stonstad commented 3 years ago

Hey @JonathanMagnan. Your scenario above works. In my case, my x and y variables also have nested parameters. So if the variable and property is X.FOO... x.FOO and X.FOO works, but x.foo does not.

JonathanMagnan commented 3 years ago

Hello @stonstad ,

We investigate it but unfortunately, we will postpone it due to the difficulty of doing it on our side (A lot of change is required if we want to do it correctly).

This is indeed something that we will want to implement but we currently missing a lot of time which makes it impossible to make this request.

We will surely look at it again in around 2-3 months but for now, that will not be supported.

Best Regards,

Jon

stonstad commented 3 years ago

OK, thank you for your response, Jon. This is a very important feature for us. My client is a paid user. We look forward to learning of its availability.

stonstad commented 3 years ago

From the documentation here (https://eval-expression.net/options) it looks like this should work?

// using Z.Expressions; // Don't forget to include this.
var context = new EvalContext();

// Make member case insensitive (Math.pOW = Math.Pow)
context.BindingFlags = BindingFlags.IgnoreCase | context.BindingFlags
JonathanMagnan commented 3 years ago

BindingFlags are from properties and fields from typed type.

ExpandoObject the way you want to use it is a whole different thing.

stonstad commented 3 years ago

Thanks, @JonathanMagnan. I'm wondering if there might be a way to convert an ExpandoObject into a true dynamic type to enable this feature. I think I could serialize the object graph, and then deserialize it back to dynamic, but that is computationally expensive...

stonstad commented 3 years ago

OK, just another thought here. What if there was an EvalDictionary<string, object> which stores keys as lower case? An overload to Eval could accept this EvalDictionary in place of an Expando IDictionary.

stonstad commented 3 years ago

Thank you for resolving per #99!

JonathanMagnan commented 3 years ago

Awesome ;) We will close it in this case.