Search code examples
c#linqdynamicexpressiondynamic-linq

Dynamic linq not correctly apply on list of DynamicClass


I'm trying to use dynamic linq over DynamicClass list. From external source I'm getting field.Name = "firstName" and field.Value = "firstValue".

   var dynamicIndexes = new List<DynamicClass>();

   var props = new DynamicProperty[]
   {
       new DynamicProperty(field.Name, typeof(string))
   };

   Type type = DynamicClassFactory.CreateType(props);

   var dynamicClass = Activator.CreateInstance(type) as DynamicClass;
   dynamicClass.SetDynamicPropertyValue<string>(field.Name, field.Value);

   dynamicIndexes.Add(dynamicClass);

   var query = dynamicIndexes.AsQueryable();
   bool isValid = query.Any("firstName eq \"firstValue\"");

But I'm getting isValid as false.

I did following tests to understand the issue:

added following code line at the beginning, to overwrite the value and then I'm getting isValid as true.

   field.Value = "firstValue";

but if I change that as follows then I'm getting isValid as false.

   byte[] utfBytes = Encoding.Default.GetBytes("firstValue");
   field.Value = Encoding.Default.GetString(utfBytes);

What I'm missing? is this issue related to encoding?

Update

As suggested here this is a limitation with dynamic linq. Can you suggest an alternative solution/library to filter DynamicClass list with a query expression.


Solution

  • The bug (and there seems to be a bug with the dynamic link expressions) is not related to encodings. There are not even different encodings used by the code in the question; just one encoding: the default encoding. The code in the question does not demonstrate a scenario where different encodings are being used or otherwise changed between, so i don't know how the asker could jump to the conclusion of different encodings being at play here...

    Rather, the bug seems to be related to whether strings are being interned or not. query.Any("firstName eq \"firstValue\""); will only work as expected and yield true, if the string instance in firstName is interned.

    If the string is not interned (which is typically the case for string dynamically/programmatically created during the runtime of the program), even if its value is precisely "firstValue", the result will be false, regardless of the actual value of the string.

    The same bug/effect can be demonstrated without involving any text encoding shenanigans at all by replacing the Encoding.Default.GetBytes/Encoding.Default.GetString combo with:

    var cc = "firstValue".ToCharArray();
    field.Value = new string(cc);