From 16d0eb52f44ccac992ccbcc03ed8cfdec98035ef Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Sun, 28 Jun 2026 22:47:41 +0200 Subject: [PATCH 1/3] Add some more unit tests for DynamicExpressionParser.ParseLambda (#985) --- .../Parser/KeywordsHelper.cs | 4 +-- .../DynamicExpressionParserTests.cs | 33 +++++++++++++++---- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/System.Linq.Dynamic.Core/Parser/KeywordsHelper.cs b/src/System.Linq.Dynamic.Core/Parser/KeywordsHelper.cs index 1e816384..977aebb5 100644 --- a/src/System.Linq.Dynamic.Core/Parser/KeywordsHelper.cs +++ b/src/System.Linq.Dynamic.Core/Parser/KeywordsHelper.cs @@ -29,10 +29,10 @@ internal class KeywordsHelper : IKeywordsHelper private readonly Dictionary> _mappings; // Pre-defined Types are not IgnoreCase - private static readonly Dictionary PreDefinedTypeMapping = new(); + private static readonly Dictionary PreDefinedTypeMapping = []; // Custom DefinedTypes are not IgnoreCase - private readonly Dictionary _customTypeMapping = new(); + private readonly Dictionary _customTypeMapping = []; static KeywordsHelper() { diff --git a/test/System.Linq.Dynamic.Core.Tests/DynamicExpressionParserTests.cs b/test/System.Linq.Dynamic.Core.Tests/DynamicExpressionParserTests.cs index 4417d1a0..5ad3338d 100644 --- a/test/System.Linq.Dynamic.Core.Tests/DynamicExpressionParserTests.cs +++ b/test/System.Linq.Dynamic.Core.Tests/DynamicExpressionParserTests.cs @@ -82,7 +82,7 @@ public int this[int i1] get => i1 + "-" + i2; } } - + private class ComplexParseLambda1Result { public int? Age; @@ -730,7 +730,7 @@ public void DynamicExpressionParser_ParseLambda_Indexer1D() // Assert Check.That(result).Equals(4); } - + [Fact] public void DynamicExpressionParser_ParseLambda_Indexer2D() { @@ -757,7 +757,7 @@ public void DynamicExpressionParser_ParseLambda_Indexer2D() // Assert Check.That(result).Equals("3-1"); } - + [Fact] public void DynamicExpressionParser_ParseLambda_IndexerParameterMismatch() { @@ -772,11 +772,32 @@ public void DynamicExpressionParser_ParseLambda_IndexerParameterMismatch() { Expression.Parameter(typeof(ClassWithIndexers), "myObj") }; - + Assert.Throws(() => DynamicExpressionParser.ParseLambda(config, false, expressionParams, null, "myObj[3,\"1\",1]")); } + [Fact] + public void DynamicExpressionParser_ParseLambda_Int16_CaseSensitive_IsValid() + { + // Act + var lambda = DynamicExpressionParser.ParseLambda(typeof(object), null, "Int16(5)"); + var result = lambda.Compile().DynamicInvoke("x"); + + // Assert + result.Should().Be(5); + } + + [Fact] + public void DynamicExpressionParser_ParseLambda_Int16_CaseInsensitive_Throws() + { + // Act + Action act = () => DynamicExpressionParser.ParseLambda(typeof(object), null, "int16(5)"); + + // Assert + act.Should().Throw(); + } + [Fact] public void DynamicExpressionParser_ParseLambda_DuplicateParameterNames_ThrowsException() { @@ -989,7 +1010,7 @@ public void DynamicExpressionParser_ParseLambda_HexToLong(string expression, lon var parameters = Array.Empty(); // Act - var lambda = DynamicExpressionParser.ParseLambda( parameters, typeof(long), expression); + var lambda = DynamicExpressionParser.ParseLambda(parameters, typeof(long), expression); var result = lambda.Compile().DynamicInvoke(); // Assert @@ -2372,6 +2393,6 @@ public DefaultDynamicLinqCustomTypeProviderForGenericExtensionMethod() : base(Pa } public override HashSet GetCustomTypes() => - [..base.GetCustomTypes(), typeof(Methods), typeof(MethodsItemExtension)]; + [.. base.GetCustomTypes(), typeof(Methods), typeof(MethodsItemExtension)]; } } \ No newline at end of file From 807df3e4485d19c53f2355b9501e312e6dd82883 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Tue, 30 Jun 2026 17:23:31 +0200 Subject: [PATCH 2/3] By default, also support WellKnownTypes like StringComparer (#984) * By default, also support WellKnownTypes like StringComparer * . --- ...umerationsAndWellKnownTypesFromMscorlib.cs | 104 ++++++++++++++++++ .../Parser/EnumerationsFromMscorlib.cs | 59 ---------- .../Parser/ExpressionParser.cs | 11 +- .../Parser/KeywordsHelper.cs | 2 +- .../ExpressionTests.cs | 32 ++++++ 5 files changed, 147 insertions(+), 61 deletions(-) create mode 100644 src/System.Linq.Dynamic.Core/Parser/EnumerationsAndWellKnownTypesFromMscorlib.cs delete mode 100644 src/System.Linq.Dynamic.Core/Parser/EnumerationsFromMscorlib.cs 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 977aebb5..9b88ec9c 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() { From 55b4865296f381133532ef9565496a10252b054b Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Sat, 11 Jul 2026 11:50:27 +0200 Subject: [PATCH 3/3] v1.7.3 --- CHANGELOG.md | 7 +++ Generate-ReleaseNotes.bat | 2 +- .../EFDynamicQueryableExtensions.cs | 60 +++++++++---------- ...ueryableWithFormattableStringExtensions.cs | 6 +- .../ExpressionTests.cs | 1 - version.xml | 2 +- 6 files changed, 42 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41364989..aee65783 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# v1.7.3 (11 July 2026) +- [#981](https://github.com/zzzprojects/System.Linq.Dynamic.Core/pull/981) - Fix MethodFinder.FirstIsBetterThanSecond [bug] contributed by [StefH](https://github.com/StefH) +- [#984](https://github.com/zzzprojects/System.Linq.Dynamic.Core/pull/984) - By default, also support WellKnownTypes like StringComparer [feature] contributed by [StefH](https://github.com/StefH) +- [#985](https://github.com/zzzprojects/System.Linq.Dynamic.Core/pull/985) - Add some more unit tests for DynamicExpressionParser.ParseLambda [test] contributed by [StefH](https://github.com/StefH) +- [#980](https://github.com/zzzprojects/System.Linq.Dynamic.Core/issues/980) - IndexOutOfRangeException in MethodFinder.FirstIsBetterThanSecond after upgrading to v1.7.2 [bug] +- [#983](https://github.com/zzzprojects/System.Linq.Dynamic.Core/issues/983) - How to IEnumerable<string>.Contains(x, StringComparer.OrdinalIgnoreCase) ? [feature] + # v1.7.2 (04 April 2026) - [#971](https://github.com/zzzprojects/System.Linq.Dynamic.Core/pull/971) - Fix some sonarcloud issues [refactor] contributed by [StefH](https://github.com/StefH) - [#974](https://github.com/zzzprojects/System.Linq.Dynamic.Core/pull/974) - Fix unhandled exceptions from malformed expression strings [bug] contributed by [Copilot](https://github.com/apps/copilot-swe-agent) diff --git a/Generate-ReleaseNotes.bat b/Generate-ReleaseNotes.bat index 7377bb34..33407128 100644 --- a/Generate-ReleaseNotes.bat +++ b/Generate-ReleaseNotes.bat @@ -1,5 +1,5 @@ rem https://github.com/StefH/GitHubReleaseNotes -SET version=v1.7.2 +SET version=v1.7.3 GitHubReleaseNotes --output CHANGELOG.md --exclude-labels known_issue out_of_scope not_planned invalid question documentation wontfix environment duplicate --language en --version %version% --token %GH_TOKEN% diff --git a/src/Microsoft.EntityFrameworkCore.DynamicLinq.EFCore3/EFDynamicQueryableExtensions.cs b/src/Microsoft.EntityFrameworkCore.DynamicLinq.EFCore3/EFDynamicQueryableExtensions.cs index 1e3a5d6e..68bd90a0 100644 --- a/src/Microsoft.EntityFrameworkCore.DynamicLinq.EFCore3/EFDynamicQueryableExtensions.cs +++ b/src/Microsoft.EntityFrameworkCore.DynamicLinq.EFCore3/EFDynamicQueryableExtensions.cs @@ -52,7 +52,7 @@ public static class EntityFrameworkDynamicQueryableExtensions [PublicAPI] public static Task AllAsync([NotNull] this IQueryable source, [NotNull] string predicate, [CanBeNull] params object[] args) { - return AllAsync(source, predicate, default(CancellationToken), args); + return AllAsync(source, predicate, default, args); } /// @@ -74,7 +74,7 @@ public static Task AllAsync([NotNull] this IQueryable source, [NotNull] st /// A task that represents the asynchronous operation. The task result contains true if every element of the source sequence passes the test in the specified predicate; otherwise, false. /// [PublicAPI] - public static Task AllAsync([NotNull] this IQueryable source, [NotNull] string predicate, CancellationToken cancellationToken = default(CancellationToken), [CanBeNull] params object[] args) + public static Task AllAsync([NotNull] this IQueryable source, [NotNull] string predicate, CancellationToken cancellationToken = default, [CanBeNull] params object[] args) { Check.NotNull(source, nameof(source)); Check.NotEmpty(predicate, nameof(predicate)); @@ -106,7 +106,7 @@ public static Task AllAsync([NotNull] this IQueryable source, [NotNull] st /// A task that represents the asynchronous operation. The task result contains true if the source sequence contains any elements; otherwise, false. /// [PublicAPI] - public static Task AnyAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = default(CancellationToken)) + public static Task AnyAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = default) { Check.NotNull(source, nameof(source)); Check.NotNull(cancellationToken, nameof(cancellationToken)); @@ -134,7 +134,7 @@ public static Task AllAsync([NotNull] this IQueryable source, [NotNull] st [PublicAPI] public static Task AnyAsync([NotNull] this IQueryable source, [NotNull] string predicate, [CanBeNull] params object[] args) { - return AnyAsync(source, predicate, default(CancellationToken), args); + return AnyAsync(source, predicate, default, args); } /// @@ -156,7 +156,7 @@ public static Task AnyAsync([NotNull] this IQueryable source, [NotNull] st /// A task that represents the asynchronous operation. The task result contains true if the source sequence contains any elements; otherwise, false. /// [PublicAPI] - public static Task AnyAsync([NotNull] this IQueryable source, [NotNull] string predicate, CancellationToken cancellationToken = default(CancellationToken), [CanBeNull] params object[] args) + public static Task AnyAsync([NotNull] this IQueryable source, [NotNull] string predicate, CancellationToken cancellationToken = default, [CanBeNull] params object[] args) { Check.NotNull(source, nameof(source)); Check.NotEmpty(predicate, nameof(predicate)); @@ -188,7 +188,7 @@ public static Task AnyAsync([NotNull] this IQueryable source, [NotNull] st /// A task that represents the asynchronous operation. The task result contains the average of the sequence of values. /// [PublicAPI] - public static Task AverageAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = default(CancellationToken)) + public static Task AverageAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = default) { Check.NotNull(source, nameof(source)); Check.NotNull(cancellationToken, nameof(cancellationToken)); @@ -218,7 +218,7 @@ public static Task AnyAsync([NotNull] this IQueryable source, [NotNull] st [PublicAPI] public static Task AverageAsync([NotNull] this IQueryable source, [NotNull] string selector, [CanBeNull] params object[] args) { - return AverageAsync(source, selector, default(CancellationToken), args); + return AverageAsync(source, selector, default, args); } /// @@ -242,7 +242,7 @@ public static Task AverageAsync([NotNull] this IQueryable source, [NotNu /// predicate; otherwise, false. /// [PublicAPI] - public static Task AverageAsync([NotNull] this IQueryable source, [NotNull] string selector, CancellationToken cancellationToken = default(CancellationToken), [CanBeNull] params object[] args) + public static Task AverageAsync([NotNull] this IQueryable source, [NotNull] string selector, CancellationToken cancellationToken = default, [CanBeNull] params object[] args) { Check.NotNull(source, nameof(source)); Check.NotEmpty(selector, nameof(selector)); @@ -275,7 +275,7 @@ public static Task AverageAsync([NotNull] this IQueryable source, [NotNu /// The task result contains the number of elements in the input sequence. /// [PublicAPI] - public static Task CountAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = default(CancellationToken)) + public static Task CountAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = default) { Check.NotNull(source, nameof(source)); Check.NotNull(cancellationToken, nameof(cancellationToken)); @@ -305,7 +305,7 @@ public static Task AverageAsync([NotNull] this IQueryable source, [NotNu [PublicAPI] public static Task CountAsync([NotNull] this IQueryable source, [NotNull] string predicate, [CanBeNull] params object[] args) { - return CountAsync(source, default(CancellationToken), predicate, args); + return CountAsync(source, default, predicate, args); } /// @@ -362,7 +362,7 @@ public static Task CountAsync([NotNull] this IQueryable source, Cancellatio /// The task result contains the first element in . /// [PublicAPI] - public static Task FirstAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = default(CancellationToken)) + public static Task FirstAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = default) { Check.NotNull(source, nameof(source)); @@ -391,7 +391,7 @@ public static Task CountAsync([NotNull] this IQueryable source, Cancellatio [PublicAPI] public static Task FirstAsync([NotNull] this IQueryable source, [NotNull] string predicate, [CanBeNull] params object[] args) { - return FirstAsync(source, default(CancellationToken), predicate, args); + return FirstAsync(source, default, predicate, args); } /// @@ -448,7 +448,7 @@ public static Task FirstAsync([NotNull] this IQueryable source, Cancell /// is empty; otherwise, the first element in . /// [PublicAPI] - public static Task FirstOrDefaultAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = default(CancellationToken)) + public static Task FirstOrDefaultAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = default) { Check.NotNull(source, nameof(source)); Check.NotNull(cancellationToken, nameof(cancellationToken)); @@ -480,7 +480,7 @@ public static Task FirstAsync([NotNull] this IQueryable source, Cancell [PublicAPI] public static Task FirstOrDefaultAsync([NotNull] this IQueryable source, [NotNull] string predicate, [CanBeNull] params object[] args) { - return FirstOrDefaultAsync(source, default(CancellationToken), predicate, args); + return FirstOrDefaultAsync(source, default, predicate, args); } /// @@ -539,7 +539,7 @@ public static Task FirstOrDefaultAsync([NotNull] this IQueryable source /// The task result contains the last element in . /// [PublicAPI] - public static Task LastAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = default(CancellationToken)) + public static Task LastAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = default) { Check.NotNull(source, nameof(source)); @@ -568,7 +568,7 @@ public static Task FirstOrDefaultAsync([NotNull] this IQueryable source [PublicAPI] public static Task LastAsync([NotNull] this IQueryable source, [NotNull] string predicate, [CanBeNull] params object[] args) { - return LastAsync(source, default(CancellationToken), predicate, args); + return LastAsync(source, default, predicate, args); } /// @@ -625,7 +625,7 @@ public static Task LastAsync([NotNull] this IQueryable source, Cancella /// is empty; otherwise, the last element in . /// [PublicAPI] - public static Task LastOrDefaultAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = default(CancellationToken)) + public static Task LastOrDefaultAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = default) { Check.NotNull(source, nameof(source)); Check.NotNull(cancellationToken, nameof(cancellationToken)); @@ -657,7 +657,7 @@ public static Task LastAsync([NotNull] this IQueryable source, Cancella [PublicAPI] public static Task LastOrDefaultAsync([NotNull] this IQueryable source, [NotNull] string predicate, [CanBeNull] params object[] args) { - return LastOrDefaultAsync(source, default(CancellationToken), predicate, args); + return LastOrDefaultAsync(source, default, predicate, args); } /// @@ -716,7 +716,7 @@ public static Task LastOrDefaultAsync([NotNull] this IQueryable source, /// The task result contains the number of elements in the input sequence. /// [PublicAPI] - public static Task LongCountAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = default(CancellationToken)) + public static Task LongCountAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = default) { Check.NotNull(source, nameof(source)); Check.NotNull(cancellationToken, nameof(cancellationToken)); @@ -746,7 +746,7 @@ public static Task LastOrDefaultAsync([NotNull] this IQueryable source, [PublicAPI] public static Task LongCountAsync([NotNull] this IQueryable source, [NotNull] string predicate, [CanBeNull] params object[] args) { - return LongCountAsync(source, default(CancellationToken), predicate, args); + return LongCountAsync(source, default, predicate, args); } /// @@ -803,7 +803,7 @@ public static Task LongCountAsync([NotNull] this IQueryable source, Cancel /// A task that represents the asynchronous operation. The task result contains the single element of the input sequence that satisfies the condition in predicate. /// [PublicAPI] - public static Task SingleOrDefaultAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = default(CancellationToken)) + public static Task SingleOrDefaultAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = default) { Check.NotNull(source, nameof(source)); Check.NotNull(cancellationToken, nameof(cancellationToken)); @@ -832,7 +832,7 @@ public static Task LongCountAsync([NotNull] this IQueryable source, Cancel [PublicAPI] public static Task SingleOrDefaultAsync([NotNull] this IQueryable source, [NotNull] string predicate, [CanBeNull] params object[] args) { - return SingleOrDefaultAsync(source, default(CancellationToken), predicate, args); + return SingleOrDefaultAsync(source, default, predicate, args); } /// @@ -886,7 +886,7 @@ public static Task SingleOrDefaultAsync([NotNull] this IQueryable sourc /// The task result contains sum of the values in the sequence. /// [PublicAPI] - public static Task SumAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = default(CancellationToken)) + public static Task SumAsync([NotNull] this IQueryable source, CancellationToken cancellationToken = default) { Check.NotNull(source, nameof(source)); Check.NotNull(cancellationToken, nameof(cancellationToken)); @@ -916,7 +916,7 @@ public static Task SingleOrDefaultAsync([NotNull] this IQueryable sourc [PublicAPI] public static Task SumAsync([NotNull] this IQueryable source, [NotNull] string selector, [CanBeNull] params object[] args) { - return SumAsync(source, default(CancellationToken), selector, args); + return SumAsync(source, default, selector, args); } /// @@ -963,7 +963,7 @@ public static Task SumAsync([NotNull] this IQueryable source, Cancellat .GetMethod(nameof(ExecuteAsync), BindingFlags.Static | BindingFlags.NonPublic, null, new[] { typeof(MethodInfo), typeof(IQueryable), typeof(CancellationToken) }, null); #endif - private static Task ExecuteDynamicAsync(MethodInfo operatorMethodInfo, IQueryable source, CancellationToken cancellationToken = default(CancellationToken)) + private static Task ExecuteDynamicAsync(MethodInfo operatorMethodInfo, IQueryable source, CancellationToken cancellationToken = default) { var executeAsyncMethod = _executeAsyncMethod.MakeGenericMethod(operatorMethodInfo.ReturnType); @@ -973,7 +973,7 @@ public static Task SumAsync([NotNull] this IQueryable source, Cancellat return castedTask; } - private static Task ExecuteAsync(MethodInfo operatorMethodInfo, IQueryable source, CancellationToken cancellationToken = default(CancellationToken)) + private static Task ExecuteAsync(MethodInfo operatorMethodInfo, IQueryable source, CancellationToken cancellationToken = default) { #if EFCORE var provider = source.Provider as IAsyncQueryProvider; @@ -1002,7 +1002,7 @@ public static Task SumAsync([NotNull] this IQueryable source, Cancellat throw new InvalidOperationException(Res.IQueryableProviderNotAsync); } - private static Task ExecuteAsync(MethodInfo operatorMethodInfo, IQueryable source, LambdaExpression expression, CancellationToken cancellationToken = default(CancellationToken)) + private static Task ExecuteAsync(MethodInfo operatorMethodInfo, IQueryable source, LambdaExpression expression, CancellationToken cancellationToken = default) => ExecuteAsync(operatorMethodInfo, source, Expression.Quote(expression), cancellationToken); private static readonly MethodInfo _executeAsyncMethodWithExpression = @@ -1014,7 +1014,7 @@ public static Task SumAsync([NotNull] this IQueryable source, Cancellat .GetMethod(nameof(ExecuteAsync), BindingFlags.Static | BindingFlags.NonPublic, null, new[] { typeof(MethodInfo), typeof(IQueryable), typeof(Expression), typeof(CancellationToken) }, null); #endif - private static Task ExecuteDynamicAsync(MethodInfo operatorMethodInfo, IQueryable source, Expression expression, CancellationToken cancellationToken = default(CancellationToken)) + private static Task ExecuteDynamicAsync(MethodInfo operatorMethodInfo, IQueryable source, Expression expression, CancellationToken cancellationToken = default) { var executeAsyncMethod = _executeAsyncMethodWithExpression.MakeGenericMethod(operatorMethodInfo.ReturnType); @@ -1024,7 +1024,7 @@ public static Task SumAsync([NotNull] this IQueryable source, Cancellat return castedTask; } - private static Task ExecuteAsync(MethodInfo operatorMethodInfo, IQueryable source, Expression expression, CancellationToken cancellationToken = default(CancellationToken)) + private static Task ExecuteAsync(MethodInfo operatorMethodInfo, IQueryable source, Expression expression, CancellationToken cancellationToken = default) { #if EFCORE var provider = source.Provider as IAsyncQueryProvider; @@ -1081,7 +1081,7 @@ private static IQueryable CastSource(IQueryable source, MethodInfo operatorMetho return source; } - private static Task ExecuteAsync(IAsyncQueryProvider provider, Expression expression, CancellationToken cancellationToken = default(CancellationToken)) + private static Task ExecuteAsync(IAsyncQueryProvider provider, Expression expression, CancellationToken cancellationToken = default) { if (typeof(TResult) == typeof(object) && expression.Type != typeof(object)) { diff --git a/src/Microsoft.EntityFrameworkCore.DynamicLinq.EFCore3/EFDynamicQueryableWithFormattableStringExtensions.cs b/src/Microsoft.EntityFrameworkCore.DynamicLinq.EFCore3/EFDynamicQueryableWithFormattableStringExtensions.cs index 2a75ae60..ae250610 100644 --- a/src/Microsoft.EntityFrameworkCore.DynamicLinq.EFCore3/EFDynamicQueryableWithFormattableStringExtensions.cs +++ b/src/Microsoft.EntityFrameworkCore.DynamicLinq.EFCore3/EFDynamicQueryableWithFormattableStringExtensions.cs @@ -43,7 +43,7 @@ public static Task AllInterpolatedAsync([NotNull] this IQueryable source, } [PublicAPI] - public static Task AllInterpolatedAsync([NotNull] this IQueryable source, [NotNull] FormattableString predicate, CancellationToken cancellationToken = default(CancellationToken)) + public static Task AllInterpolatedAsync([NotNull] this IQueryable source, [NotNull] FormattableString predicate, CancellationToken cancellationToken = default) { string predicateStr = ParseFormattableString(predicate, out object[] args); return EntityFrameworkDynamicQueryableExtensions.AllAsync(source, predicateStr, cancellationToken, args); @@ -57,7 +57,7 @@ public static Task AnyInterpolatedAsync([NotNull] this IQueryable source, } [PublicAPI] - public static Task AnyInterpolatedAsync([NotNull] this IQueryable source, [NotNull] FormattableString predicate, CancellationToken cancellationToken = default(CancellationToken)) + public static Task AnyInterpolatedAsync([NotNull] this IQueryable source, [NotNull] FormattableString predicate, CancellationToken cancellationToken = default) { string predicateStr = ParseFormattableString(predicate, out object[] args); return EntityFrameworkDynamicQueryableExtensions.AnyAsync(source, predicateStr, cancellationToken, args); @@ -72,7 +72,7 @@ public static Task AverageInterpolatedAsync([NotNull] this IQueryable so [PublicAPI] - public static Task AverageInterpolatedAsync([NotNull] this IQueryable source, [NotNull] FormattableString selector, CancellationToken cancellationToken = default(CancellationToken)) + public static Task AverageInterpolatedAsync([NotNull] this IQueryable source, [NotNull] FormattableString selector, CancellationToken cancellationToken = default) { string selectorStr = ParseFormattableString(selector, out object[] args); return EntityFrameworkDynamicQueryableExtensions.AverageAsync(source, selectorStr, cancellationToken, args); diff --git a/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs b/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs index d3d2a1e3..84e5917b 100644 --- a/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs +++ b/test/System.Linq.Dynamic.Core.Tests/ExpressionTests.cs @@ -5,7 +5,6 @@ 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; diff --git a/version.xml b/version.xml index 257b812f..9fefde31 100644 --- a/version.xml +++ b/version.xml @@ -1,5 +1,5 @@ - 2 + 3 \ No newline at end of file