diff --git a/src/System.Linq.Dynamic.Core/Parser/EnumerationsAndWellKnownTypesFromMscorlib.cs b/src/System.Linq.Dynamic.Core/Parser/EnumerationsAndWellKnownTypesFromMscorlib.cs
new file mode 100644
index 00000000..78f64cb6
--- /dev/null
+++ b/src/System.Linq.Dynamic.Core/Parser/EnumerationsAndWellKnownTypesFromMscorlib.cs
@@ -0,0 +1,104 @@
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Xml;
+using System.Xml.Linq;
+
+namespace System.Linq.Dynamic.Core.Parser;
+
+internal static class EnumerationsAndWellKnownTypesFromMscorlib
+{
+ private readonly static string SystemPrivateCoreLib = typeof(StringComparer).GetTypeInfo().Assembly.FullName!;
+ private readonly static string SystemPrivateUri = typeof(UriFormat).GetTypeInfo().Assembly.FullName!;
+ private readonly static string SystemPrivateXml = typeof(XmlNodeType).GetTypeInfo().Assembly.FullName!;
+ private readonly static string SystemPrivateXmlLinq = typeof(XObject).GetTypeInfo().Assembly.FullName!;
+
+ ///
+ /// Enum types and well-known types.
+ ///
+ public static readonly ConcurrentDictionary PredefinedEnumerationTypes = new(StringComparer.OrdinalIgnoreCase);
+
+ static EnumerationsAndWellKnownTypesFromMscorlib()
+ {
+ var list = AddEnumsAndWellKnownTypesFromAssembly(SystemPrivateUri);
+ list.AddRange(AddEnumsAndWellKnownTypesFromAssembly(SystemPrivateCoreLib));
+ list.AddRange(AddEnumsAndWellKnownTypesFromAssembly(SystemPrivateXml));
+ list.AddRange(AddEnumsAndWellKnownTypesFromAssembly(SystemPrivateXmlLinq));
+
+#if !(NET35 || NETSTANDARD1_3)
+ var systemPrivateDataContractSerialization = typeof(Runtime.Serialization.DataContractResolver).GetTypeInfo().Assembly.FullName!;
+ list.AddRange(AddEnumsAndWellKnownTypesFromAssembly(systemPrivateDataContractSerialization));
+#endif
+ foreach (var group in list.GroupBy(t => t.Name))
+ {
+ Add(group);
+ }
+ }
+
+ private static List AddEnumsAndWellKnownTypesFromAssembly(string assemblyName)
+ {
+ try
+ {
+ var assembly = Assembly.Load(new AssemblyName(assemblyName));
+ var types = assembly.GetTypes().ToArray();
+
+ var enumTypes = types.Where(t => t.GetTypeInfo().IsEnum && t.GetTypeInfo().IsPublic);
+ var enumLikeTypes = FindEnumLikeTypes(types.Where(x => x == typeof(StringComparer)).ToArray());
+
+ return enumTypes.Union(enumLikeTypes).ToList();
+ }
+ catch
+ {
+ return [];
+ }
+ }
+
+ private static Type[] FindEnumLikeTypes(Type[] types)
+ {
+ try
+ {
+ return types
+ .Where(t => t.GetTypeInfo().IsPublic && !t.GetTypeInfo().IsEnum && HasStaticPropertiesOrFieldsOfOwnType(t))
+ .ToArray();
+ }
+ catch
+ {
+ return [];
+ }
+ }
+
+ private static bool HasStaticPropertiesOrFieldsOfOwnType(Type type)
+ {
+ var baseType = type.GetTypeInfo().BaseType;
+
+ var anyStaticProperties = type.GetProperties(BindingFlags.Public | BindingFlags.Static)
+ .Any(p => p.PropertyType == type || p.PropertyType == baseType);
+
+ if (anyStaticProperties)
+ {
+ return true;
+ }
+
+ var anyStaticFields = type.GetFields(BindingFlags.Public | BindingFlags.Static)
+ .Any(f => f.FieldType == type || f.FieldType == baseType);
+
+ return anyStaticFields;
+ }
+
+ private static void Add(IGrouping group)
+ {
+ if (group.Count() == 1)
+ {
+ var singleType = group.Single();
+ PredefinedEnumerationTypes.TryAdd(group.Key, singleType);
+ PredefinedEnumerationTypes.TryAdd(singleType.FullName!, singleType);
+ }
+ else
+ {
+ foreach (var fullType in group)
+ {
+ PredefinedEnumerationTypes.TryAdd(fullType.FullName!, fullType);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/System.Linq.Dynamic.Core/Parser/EnumerationsFromMscorlib.cs b/src/System.Linq.Dynamic.Core/Parser/EnumerationsFromMscorlib.cs
deleted file mode 100644
index 6b2f4b25..00000000
--- a/src/System.Linq.Dynamic.Core/Parser/EnumerationsFromMscorlib.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-using System.Collections.Concurrent;
-using System.Collections.Generic;
-using System.Reflection;
-
-namespace System.Linq.Dynamic.Core.Parser
-{
- internal static class EnumerationsFromMscorlib
- {
- ///
- /// All Enum types from mscorlib/netstandard.
- ///
- public static readonly IDictionary PredefinedEnumerationTypes = new ConcurrentDictionary();
-
- static EnumerationsFromMscorlib()
- {
- var list = new List(AddEnumsFromAssembly(typeof(UriFormat).GetTypeInfo().Assembly.FullName!));
-
-#if !(UAP10_0 || NETSTANDARD || NET35 || NETCOREAPP)
- list.AddRange(AddEnumsFromAssembly("mscorlib"));
-#else
- list.AddRange(AddEnumsFromAssembly("System.Runtime"));
- list.AddRange(AddEnumsFromAssembly("System.Private.Corelib"));
-#endif
- foreach (var group in list.GroupBy(t => t.Name))
- {
- Add(group);
- }
- }
-
- private static IEnumerable AddEnumsFromAssembly(string assemblyName)
- {
- try
- {
- return Assembly.Load(new AssemblyName(assemblyName)).GetTypes().Where(t => t.GetTypeInfo().IsEnum && t.GetTypeInfo().IsPublic);
- }
- catch
- {
- return Enumerable.Empty();
- }
- }
-
- private static void Add(IGrouping group)
- {
- if (group.Count() == 1)
- {
- var singleType = group.Single();
- PredefinedEnumerationTypes.Add(group.Key, singleType);
- PredefinedEnumerationTypes.Add(singleType.FullName!, singleType);
- }
- else
- {
- foreach (var fullType in group)
- {
- PredefinedEnumerationTypes.Add(fullType.FullName!, fullType);
- }
- }
- }
- }
-}
diff --git a/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs b/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs
index 4a6319aa..d93cfde4 100644
--- a/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs
+++ b/src/System.Linq.Dynamic.Core/Parser/ExpressionParser.cs
@@ -2317,7 +2317,16 @@ private bool TryParseEnumerable(Expression instance, Type enumerableType, string
{
if (new[] { "Concat", "Contains", "ContainsKey", "DefaultIfEmpty", "Except", "Intersect", "Skip", "Take", "Union", "SequenceEqual" }.Contains(methodName))
{
- args = [instance, args[0]];
+ if (args.Length == 1)
+ {
+ args = [instance, args[0]];
+ }
+ else
+ {
+ var argsAsList = new List { instance };
+ argsAsList.AddRange(args);
+ args = argsAsList.ToArray();
+ }
}
else
{
diff --git a/src/System.Linq.Dynamic.Core/Parser/KeywordsHelper.cs b/src/System.Linq.Dynamic.Core/Parser/KeywordsHelper.cs
index 1e816384..6adffdf5 100644
--- a/src/System.Linq.Dynamic.Core/Parser/KeywordsHelper.cs
+++ b/src/System.Linq.Dynamic.Core/Parser/KeywordsHelper.cs
@@ -118,7 +118,7 @@ public bool TryGetValue(string text, out AnyOf value)
}
// 4. Try to get as an enum from the system namespace
- if (_config.SupportEnumerationsFromSystemNamespace && EnumerationsFromMscorlib.PredefinedEnumerationTypes.TryGetValue(text, out var predefinedEnumType))
+ if (_config.SupportEnumerationsFromSystemNamespace && EnumerationsAndWellKnownTypesFromMscorlib.PredefinedEnumerationTypes.TryGetValue(text, out var predefinedEnumType))
{
value = predefinedEnumType;
return true;
diff --git a/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs b/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs
index 021183a5..d3d2a1e3 100644
--- a/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs
+++ b/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs
@@ -5,6 +5,8 @@
using System.Linq.Dynamic.Core.Exceptions;
using System.Linq.Dynamic.Core.Tests.Helpers;
using System.Linq.Dynamic.Core.Tests.Helpers.Models;
+using System.Net.WebSockets;
+using System.Xml;
using FluentAssertions;
using Moq;
using Newtonsoft.Json.Linq;
@@ -853,6 +855,36 @@ public void ExpressionTests_Enum()
Check.That(resultEqualStringMixedCaseParamRight.Single()).Equals(TestEnum.Var5);
}
+ [Fact]
+ public void ExpressionTests_Enum_XmlNodeType()
+ {
+ // Arrange
+ var lst = new[] { XmlNodeType.Text, XmlNodeType.Element };
+ var qry = lst.AsQueryable();
+
+ // Act
+ var result = lst.Count(it => new[] { XmlNodeType.Text }.Contains(it));
+ var dynamicResult = qry.Count("new XmlNodeType[] { XmlNodeType.Text }.Contains(it)");
+
+ // Assert
+ dynamicResult.Should().Be(result);
+ }
+
+ [Fact]
+ public void ExpressionTests_WellKnownTypes_StringComparer()
+ {
+ // Arrange
+ var lst = new[] { "test" };
+ var qry = lst.AsQueryable();
+
+ // Act
+ var result = lst.Count(it => new string[] { "Test" }.Contains(it, StringComparer.OrdinalIgnoreCase));
+ var dynamicResult = qry.Count("new string[] { \"Test\" }.Contains(it, StringComparer.OrdinalIgnoreCase)");
+
+ // Assert
+ dynamicResult.Should().Be(result);
+ }
+
[Fact]
public void ExpressionTests_Enum_Property_Equality_Using_Argument()
{