Skip to content

String concatenations fails with System.ArgumentException during parsing #845

@victorr99

Description

@victorr99

1. Description

An expression like "foo" & SomeVar fails when SomeVar is not a reference type. When Parse() is called a System.ArgumentException is raised stating that int cannot be used for object arguments. I assume the value needs to be manually boxed before being passed to string.Concat. If I create an expression manually I get the same error. When I firstly convert the value to object, the Concat works just fine.

2. Exception

Unhandled exception. System.ArgumentException: Expression of type 'System.Int32' cannot be used for parameter of type 'System.Object' of method 'System.String Concat(System.Object, System.Object)' (Parameter 'arg1')
   at System.Dynamic.Utils.ExpressionUtils.ValidateOneArgument(MethodBase method, ExpressionType nodeKind, Expression arguments, ParameterInfo pi, String methodParamName, String argumentParamName, Int32 index)
   at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, Expression arg0, Expression arg1)
   at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, IEnumerable`1 arguments)
   at System.Linq.Dynamic.Core.Parser.ExpressionHelper.GenerateStaticMethodCall(String methodName, Expression left, Expression right)
   at System.Linq.Dynamic.Core.Parser.ExpressionHelper.GenerateStringConcat(Expression left, Expression right)
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseLogicalAndOrOperator()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseIn()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseAndOperator()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseOrOperator()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseLambdaOperator()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseNullCoalescingOperator()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.ParseConditionalOperator()
   at System.Linq.Dynamic.Core.Parser.ExpressionParser.Parse(Type resultType, Boolean createParameterCtor)
   at TypeBuilderWithExpression.Program.Main(String[] args) 

3. Fiddle or Project

If you are able,

Provide a Fiddle that reproduce the issue: https://dotnetfiddle.net/25Vjsn

var parser = new ExpressionParser(
    [Expression.Parameter(typeof(int), "VarA")],
    "\"foo\" & VarA",
    [],
    null);
        
var expression = parser.Parse(typeof(string));

4. Any further technical details

This doesn't work:

var method = typeof(string)
    .GetMethods(BindingFlags.Public | BindingFlags.Static)
    .Where(m => m.Name == "Concat" && m.GetParameters().Select(p => p.ParameterType).SequenceEqual([typeof(object[])]))
    .First();

var param = Expression.Parameter(typeof(int));
var expression = Expression.Call(null, method, Expression.NewArrayInit(typeof(object), Expression.Constant("Hello"), param));

var callable = Expression.Lambda<Func<int, string>>(expression, param).Compile();
var r = callable.Invoke(20);

Console.WriteLine(r);

But this does:

var method = typeof(string)
    .GetMethods(BindingFlags.Public | BindingFlags.Static)
    .Where(m => m.Name == "Concat" && m.GetParameters().Select(p => p.ParameterType).SequenceEqual([typeof(object[])]))
    .First();

var param = Expression.Parameter(typeof(int));
var boxed = Expression.Convert(param, typeof(object));
var expression = Expression.Call(null, method, Expression.NewArrayInit(typeof(object), Expression.Constant("Hello"), boxed));

var callable = Expression.Lambda<Func<int, string>>(expression, param).Compile();
var r = callable.Invoke(20);

Console.WriteLine(r);

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions