Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Running into a ParseException in a WebGL build #767

Closed
ReginaldBull opened this issue Jan 31, 2024 · 12 comments
Closed

Running into a ParseException in a WebGL build #767

ReginaldBull opened this issue Jan 31, 2024 · 12 comments
Assignees
Labels

Comments

@ReginaldBull
Copy link

ReginaldBull commented Jan 31, 2024

1. Description

I'm using the library in a Untiy3D project. The project is build for WebGL. Running the application encounters an error as soon the execution comes to parse an expression. Inside the Unity-Editor the execution is running smoothly without any problems.

The expression itself is executing on a list of objects and returns an element where a predicate is met.

2. Exception

ParseException: No applicable aggregate method 'FirstOrDefault(Boolean)' exists
  at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseEnumerable (System.Linq.Expressions.Expression instance, System.Type elementType, System.String methodName, System.Int32 errorPos, System.Type type) [0x00000] in <00000000000000000000000000000000>:0 
  at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseMemberAccess (System.Type type, System.Linq.Expressions.Expression expression) [0x00000] in <00000000000000000000000000000000>:0 
  at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParsePrimary () [0x00000] in <00000000000000000000000000000000>:0 
  at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseUnary () [0x00000] in <00000000000000000000000000000000>:0 
  at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseArithmetic () [0x00000] in <00000000000000000000000000000000>:0 
  at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseAdditive () [0x00000] in <00000000000000000000000000000000>:0 
  at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseShiftOperator () [0x00000] in <00000000000000000000000000000000>:0 
  at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseComparisonOperator () [0x00000] in <00000000000000000000000000000000>:0 
  at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseLogicalAndOrOperator () [0x00000] in <00000000000000000000000000000000>:0 
  at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseIn () [0x00000] in <00000000000000000000000000000000>:0 
  at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseAndOperator () [0x00000] in <00000000000000000000000000000000>:0 
  at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseOrOperator () [0x00000] in <00000000000000000000000000000000>:0 
  at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseLambdaOperator () [0x00000] in <00000000000000000000000000000000>:0 
  at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseNullCoalescingOperator () [0x00000] in <00000000000000000000000000000000>:0 
  at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseConditionalOperator () [0x00000] in <00000000000000000000000000000000>:0 
  at System.Linq.Dynamic.Core.Parser.ExpressionParser.Parse (System.Type resultType, System.Boolean createParameterCtor) [0x00000] in <00000000000000000000000000000000>:0 

I'm passing my classes as custom types to the parser.

Type[] customType=....;
ParameterExpression[] parameterExpressions=....;

_parser.Parse<T>(rule.Expression, parameterExpressions, customTypes)

I will be happy giving more information if needed.

@StefH StefH self-assigned this Jan 31, 2024
@StefH
Copy link
Collaborator

StefH commented Jan 31, 2024

@ReginaldBull
Please provide a full working example dotnetfiddle

@ReginaldBull
Copy link
Author

I don't know how to provide a fiddle example for a problem that exists within a WebGL (wasm) compiled project.

@StefH
Copy link
Collaborator

StefH commented Jan 31, 2024

Can you provide the part from your own code (including the entities / dtos) and the Dynamic LINQ Expression you are trying to parse?

@ReginaldBull
Copy link
Author

Basically it all boils down to this:

public class CustomTypeProvider : DefaultDynamicLinqCustomTypeProvider
{
    private readonly HashSet<Type> _types;

    public CustomTypeProvider(Type[] types)
    {
        _types = new HashSet<Type>(types ?? new Type[]
        {
        })
        {
            typeof(Choice),
            typeof(ProductConfiguration),
            typeof(IEnumerable<>)
        };
    }

    public override HashSet<Type> GetCustomTypes() => _types;
}

public class ProductConfiguration{
    public string Code {get; private set;}
    public IEnumerable<IChoice> Choices {get; private set;}=new List<IChoice>();
}

public interface IChoice {
    string Reference{get}
}

public class Choice : IChoice{
    public string Reference {get; private set;}
}

string expression = "input.Choices.FirstOrDefault(p => p.Reference == \"MyReference\")";

Type[] customTypes = new []{
    typeof(Choice),
    typeof(ProductConfiguration),
    typeof(IEnumerable<>)
};

ParameterExpression[] parameterExpressions = new []{
    Expression.Parameter(typeof(ProductConfiguration), "input")
};

ParsingConfig config = new ParsingConfig
{
    CustomTypeProvider = new CustomTypeProvider(customTypes),
    IsCaseSensitive = false
};

EpxressionParser parser = new ExpressionParser(parameterExpressions, expression, new object[]{}, config);

Expression exp = parser.Parse<Choice>(expression, parameterExpression, customTypes);

ProductConfiguration productConfiguration = CreateValidProductConfiguration();

object[] input = new object[]{
    productConfiguration
};

var result = exp(input);

As mentioned, running it locally it works. The problem shows up when using that approach inside a Unity3D WebGL build.

@StefH
Copy link
Collaborator

StefH commented Feb 1, 2024

Can you make a simple and small Unity3D WebGL example project ?

@ReginaldBull
Copy link
Author

I created a minimal project for reproduction:

https://github.com/ReginaldBull/LinqDynamicCoreUnity3D

@StefH
Copy link
Collaborator

StefH commented Feb 3, 2024

@ReginaldBull
Thanks for the project, however this is still a very big project. Can you please make a very easy and simple test project please?

@ReginaldBull
Copy link
Author

Hello,
I removed some unnecessary folders. But this is quite a small project. The source in question can be found under the folder Assets/Scripts.

@StefH
Copy link
Collaborator

StefH commented Mar 3, 2024

@ReginaldBull
Sorry, I cannot open this project, I do not have all dependencies installed on my system.

Can you maybe use the extension method instead of directly using new ExpressionParser?

And try to write the query you want to execute first as normal LINQ query, and from that, create a the dynamic.

Example:

using System.Linq.Dynamic.Core;
using ConsoleApp1;

string expression = "Choices.FirstOrDefault(p => p.Reference == \"MyReference\")";

Type[] customTypes = new[]
{
    typeof(Choice),
    typeof(ProductConfiguration),
    typeof(IEnumerable<>)
};

var config = new ParsingConfig
{
    CustomTypeProvider = new CustomTypeProvider(customTypes),
    IsCaseSensitive = false
};

var productConfiguration = new ProductConfiguration("code");
var input = new[]
{
    productConfiguration
};

var result = input.Select(i => i.Choices.FirstOrDefault(c => c.Reference == "MyReference")).ToArray();

var resultQ = input.AsQueryable().Select(config, expression).ToDynamicArray();

@StefH StefH closed this as completed Mar 3, 2024
@StefH StefH added the question label Mar 3, 2024
@ReginaldBull
Copy link
Author

Thank you.

Today I tried with the extension method.
Running it in Unity Editor mode is working fine but as soon as the web assembly is generated it produces the same error described at the start of this issue.

@ReginaldBull
Copy link
Author

One additional finding. I tried again and debugged a bit in deep and found this exception occuring:
System.IO.FileNotFoundException: Could not load the file 'System.Private.Corelib'.

System.IO.FileNotFoundException: Could not load the file 'System.Private.Corelib'. File name: 'System.Private.Corelib' at System.AppDomain.Load (System.Reflection.AssemblyName assemblyRef, System.Security.Policy.Evidence assemblySecurity) [0x0007a] in <35594092a38441a79b40e2237d5e8762>:0 at (wrapper remoting-invoke-with-check) System.AppDomain.Load(System.Reflection.AssemblyName,System.Security.Policy.Evidence) at System.AppDomain.Load (System.Reflection.AssemblyName assemblyRef) [0x00000] in <35594092a38441a79b40e2237d5e8762>:0 at (wrapper remoting-invoke-with-check) System.AppDomain.Load(System.Reflection.AssemblyName) at System.Reflection.Assembly.Load (System.Reflection.AssemblyName assemblyRef) [0x00005] in <35594092a38441a79b40e2237d5e8762>:0 at System.Linq.Dynamic.Core.Parser.EnumerationsFromMscorlib.AddEnumsFromAssembly (System.String assemblyName) [0x00006] in <4cc38c5670114affad31d8b74c3f62b1>:0

@StefH
Copy link
Collaborator

StefH commented Mar 14, 2024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

2 participants