System.Linq.Dynamic: How to guarantee parameter order in Parse function?

120 Views Asked by At

In the code below I successfully use Microsoft's System.Linq.Dynamic in C# to evaluate string expressions similar to Javascript eval(). However, I cannot figure out how to guarantee that parameter names and corresponding values match when calling the new function. "SKU + \" \" + Name" could return 1234 Cola just as easily as Cola 1234. I have dozens of parameters.

System.Dynamic.Linq's Parse method uses Dictionary<string,object> to hold parameters internally which is my problem because Dictionary does not guarantee order like Arrays and Lists. I assume because Microsoft chose to use Dictionary that there must be some simple fix to the code below to ensure parameter values match up. Code was entered in LinqPad.

Are named parameters possible like Name: "Cola", SKU: "1234"? Is there some datatype or technique I could use to guarantee parameter names and values match? Does this require a change to Microsoft's code to replace Dictionary?

var symbols = new Dictionary<String, Object>();         // Cannot change symbols datatype
var paramExp = new List<ParameterExpression>();
var paramVal = new List<String>();

var fields = new Dictionary<String,String>();                              // Sample Data
fields["SKU"] = "1234";
fields["Name"] = "Cola";
fields["Type"] = "Drink";
var expression = "SKU + \" \" + Name";

foreach( var f in fields) {                                           // Setup Parameters
    ParameterExpression x =
        Expression.Parameter(Type.GetType("System.String"), f.Key);
    symbols.Add( f.Key, x);
    paramExp.Add( x);
    paramVal.Add( f.Value);
}

Expression body = System.Linq.Dynamic.DynamicExpression.Parse(  
    Type.GetType("System.String"), expression, symbols);

LambdaExpression e = Expression.Lambda(body, 
    paramExp.ToArray());                                      // Order may not match body

var c = e.Compile();

c.DynamicInvoke(paramVal.ToArray());             // Same here ... possible order mismatch
// c.Dump(); // outputs "1234 Cola" 

Here are the usings for above and System.Linq.Dynamic:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Linq.Dynamic;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Threading;
0

There are 0 best solutions below