diff --git a/System.Linq.Dynamic.Core.sln b/System.Linq.Dynamic.Core.sln index 7de6a7ca..be7b39fa 100644 --- a/System.Linq.Dynamic.Core.sln +++ b/System.Linq.Dynamic.Core.sln @@ -112,6 +112,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.EntityFrameworkCo EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleApp_net5.0_EF6_InMemory", "src-console\ConsoleAppEF6_InMemory\ConsoleApp_net5.0_EF6_InMemory.csproj", "{4CC563F6-5352-4A77-A8C0-DC0D77A71DBB}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApp_net6.0", "src-console\ConsoleApp_net6.0\ConsoleApp_net6.0.csproj", "{C206917D-6E90-4A31-8533-AF2DD68FF738}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -702,6 +704,22 @@ Global {4CC563F6-5352-4A77-A8C0-DC0D77A71DBB}.Release|x64.Build.0 = Release|Any CPU {4CC563F6-5352-4A77-A8C0-DC0D77A71DBB}.Release|x86.ActiveCfg = Release|Any CPU {4CC563F6-5352-4A77-A8C0-DC0D77A71DBB}.Release|x86.Build.0 = Release|Any CPU + {C206917D-6E90-4A31-8533-AF2DD68FF738}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C206917D-6E90-4A31-8533-AF2DD68FF738}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C206917D-6E90-4A31-8533-AF2DD68FF738}.Debug|ARM.ActiveCfg = Debug|Any CPU + {C206917D-6E90-4A31-8533-AF2DD68FF738}.Debug|ARM.Build.0 = Debug|Any CPU + {C206917D-6E90-4A31-8533-AF2DD68FF738}.Debug|x64.ActiveCfg = Debug|Any CPU + {C206917D-6E90-4A31-8533-AF2DD68FF738}.Debug|x64.Build.0 = Debug|Any CPU + {C206917D-6E90-4A31-8533-AF2DD68FF738}.Debug|x86.ActiveCfg = Debug|Any CPU + {C206917D-6E90-4A31-8533-AF2DD68FF738}.Debug|x86.Build.0 = Debug|Any CPU + {C206917D-6E90-4A31-8533-AF2DD68FF738}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C206917D-6E90-4A31-8533-AF2DD68FF738}.Release|Any CPU.Build.0 = Release|Any CPU + {C206917D-6E90-4A31-8533-AF2DD68FF738}.Release|ARM.ActiveCfg = Release|Any CPU + {C206917D-6E90-4A31-8533-AF2DD68FF738}.Release|ARM.Build.0 = Release|Any CPU + {C206917D-6E90-4A31-8533-AF2DD68FF738}.Release|x64.ActiveCfg = Release|Any CPU + {C206917D-6E90-4A31-8533-AF2DD68FF738}.Release|x64.Build.0 = Release|Any CPU + {C206917D-6E90-4A31-8533-AF2DD68FF738}.Release|x86.ActiveCfg = Release|Any CPU + {C206917D-6E90-4A31-8533-AF2DD68FF738}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -742,6 +760,7 @@ Global {3DA1CE3B-D1FB-4CEC-A4A6-22495CC36655} = {122BC4FA-7563-4E35-9D17-077F16F1629F} {D28F6393-B56B-40A2-AF67-E8D669F42546} = {DBD7D9B6-FCC7-4650-91AF-E6457573A68F} {4CC563F6-5352-4A77-A8C0-DC0D77A71DBB} = {7971CAEB-B9F2-416B-966D-2D697C4C1E62} + {C206917D-6E90-4A31-8533-AF2DD68FF738} = {7971CAEB-B9F2-416B-966D-2D697C4C1E62} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {94C56722-194E-4B8B-BC23-B3F754E89A20} diff --git a/src-console/ConsoleAppEF5/Program.cs b/src-console/ConsoleAppEF5/Program.cs index a10e1ac3..3b69b52f 100644 --- a/src-console/ConsoleAppEF5/Program.cs +++ b/src-console/ConsoleAppEF5/Program.cs @@ -10,6 +10,17 @@ class Program { static void Main(string[] args) { + var e = new int[0].AsQueryable(); + var q = new[] { 1 }.AsQueryable(); + + var a = q.FirstOrDefault(); + // var b = e.FirstOrDefault(44); only .NET 6.0 + + var c = q.FirstOrDefault(i => i == 0); + // var d = q.FirstOrDefault(i => i == 0, 42); only .NET 6.0 + + int y = 0; + var users = new[] { new User { FirstName = "Doe" } }.AsQueryable(); var context = new TestContext(); @@ -102,9 +113,9 @@ static void Main(string[] args) { users.Select(config, "new User(1 as FieldDoesNotExist)"); } - catch (Exception e) + catch (Exception ex) { - Console.WriteLine(e); + Console.WriteLine(ex); } foreach (dynamic x in users.Select("new (FirstName, string(\"a\") as StrA, string('c') as StrCh, string(\"\") as StrEmpty1, string('\0') as StrEmpty2, string(null) as StrNull)")) diff --git a/src-console/ConsoleApp_net6.0/ConsoleApp_net6.0.csproj b/src-console/ConsoleApp_net6.0/ConsoleApp_net6.0.csproj new file mode 100644 index 00000000..9e2ed750 --- /dev/null +++ b/src-console/ConsoleApp_net6.0/ConsoleApp_net6.0.csproj @@ -0,0 +1,13 @@ + + + + Exe + net6.0 + ConsoleApp_net6._0 + + + + + + + diff --git a/src-console/ConsoleApp_net6.0/Program.cs b/src-console/ConsoleApp_net6.0/Program.cs new file mode 100644 index 00000000..b9c1afe7 --- /dev/null +++ b/src-console/ConsoleApp_net6.0/Program.cs @@ -0,0 +1,43 @@ +using System; +using System.Linq; +using System.Linq.Dynamic.Core; + +namespace ConsoleApp_net6._0 +{ + class Program + { + static void Main(string[] args) + { + Normal(); + Dynamic(); + + int y = 0; + } + + private static void Normal() + { + var e = new int[0].AsQueryable(); + var q = new[] { 1 }.AsQueryable(); + + var a = q.FirstOrDefault(); + var b = e.FirstOrDefault(44); + + var c = q.FirstOrDefault(i => i == 0); + var d = q.FirstOrDefault(i => i == 0, 42); + + var t = q.Take(1); + } + + private static void Dynamic() + { + var e = new int[0].AsQueryable() as IQueryable; + var q = new[] { 1 }.AsQueryable() as IQueryable; + + var a = q.FirstOrDefault(); + //var b = e.FirstOrDefault(44); + + var c = q.FirstOrDefault("it == 0"); + //var d = q.FirstOrDefault(i => i == 0, 42); + } + } +} diff --git a/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs b/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs index c8cd77ab..2544850d 100644 --- a/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs +++ b/src/System.Linq.Dynamic.Core/DynamicQueryableExtensions.cs @@ -10,6 +10,7 @@ using System.Reflection; using JetBrains.Annotations; using System.Linq.Dynamic.Core.Parser; +using System.Linq.Dynamic.Core.Util; #if WINDOWS_APP using System; @@ -101,7 +102,7 @@ public static object Aggregate([NotNull] this IQueryable source, [NotNull] strin #endregion Aggregate #region All - private static readonly MethodInfo _AllPredicate = GetMethod(nameof(Queryable.All), 1); + private static readonly MethodInfo _AllPredicate = QueryableMethodFinder.GetMethod(nameof(Queryable.All), 1); /// /// Determines whether all the elements of a sequence satisfy a condition. @@ -155,7 +156,7 @@ public static bool All([NotNull] this IQueryable source, [NotNull] ParsingConfig #endregion AllAsync #region Any - private static readonly MethodInfo _any = GetMethod(nameof(Queryable.Any)); + private static readonly MethodInfo _any = QueryableMethodFinder.GetMethod(nameof(Queryable.Any)); /// /// Determines whether a sequence contains any elements. @@ -175,7 +176,7 @@ public static bool Any([NotNull] this IQueryable source) return Execute(_any, source); } - private static readonly MethodInfo _anyPredicate = GetMethod(nameof(Queryable.Any), 1); + private static readonly MethodInfo _anyPredicate = QueryableMethodFinder.GetMethod(nameof(Queryable.Any), 1); /// /// Determines whether a sequence contains any elements. @@ -245,7 +246,7 @@ public static double Average([NotNull] this IQueryable source) { Check.NotNull(source, nameof(source)); - var average = GetMethod(nameof(Queryable.Average), source.ElementType, typeof(double)); + var average = QueryableMethodFinder.GetMethod(nameof(Queryable.Average), source.ElementType, typeof(double)); return Execute(average, source); } @@ -295,7 +296,7 @@ public static double Average([NotNull] this IQueryable source, [NotNull] LambdaE Check.NotNull(source, nameof(source)); Check.NotNull(lambda, nameof(lambda)); - var averageSelector = GetMethod(nameof(Queryable.Average), lambda.GetReturnType(), typeof(double), 1); + var averageSelector = QueryableMethodFinder.GetMethod(nameof(Queryable.Average), lambda.GetReturnType(), typeof(double), 1); return Execute(averageSelector, source, lambda); } #endregion Average @@ -325,7 +326,7 @@ public static IEnumerable AsEnumerable([NotNull] this IQueryable source #endregion AsEnumerable #region Cast - private static readonly MethodInfo _cast = GetGenericMethod(nameof(Queryable.Cast)); + private static readonly MethodInfo _cast = QueryableMethodFinder.GetGenericMethod(nameof(Queryable.Cast)); /// /// Converts the elements of an to the specified type. @@ -375,7 +376,7 @@ public static IQueryable Cast([NotNull] this IQueryable source, [NotNull] string #endregion Cast #region Count - private static readonly MethodInfo _count = GetMethod(nameof(Queryable.Count)); + private static readonly MethodInfo _count = QueryableMethodFinder.GetMethod(nameof(Queryable.Count)); /// /// Returns the number of elements in a sequence. @@ -395,7 +396,7 @@ public static int Count([NotNull] this IQueryable source) return Execute(_count, source); } - private static readonly MethodInfo _countPredicate = GetMethod(nameof(Queryable.Count), 1); + private static readonly MethodInfo _countPredicate = QueryableMethodFinder.GetMethod(nameof(Queryable.Count), 1); /// /// Returns the number of elements in a sequence. @@ -448,8 +449,8 @@ public static int Count([NotNull] this IQueryable source, [NotNull] LambdaExpres #endregion Count #region DefaultIfEmpty - private static readonly MethodInfo _defaultIfEmpty = GetMethod(nameof(Queryable.DefaultIfEmpty)); - private static readonly MethodInfo _defaultIfEmptyWithParam = GetMethod(nameof(Queryable.DefaultIfEmpty), 1); + private static readonly MethodInfo _defaultIfEmpty = QueryableMethodFinder.GetMethod(nameof(Queryable.DefaultIfEmpty)); + private static readonly MethodInfo _defaultIfEmptyWithParam = QueryableMethodFinder.GetMethod(nameof(Queryable.DefaultIfEmpty), 1); /// /// Returns the elements of the specified sequence or the type parameter's default value in a singleton collection if the sequence is empty. @@ -488,7 +489,7 @@ public static IQueryable DefaultIfEmpty([NotNull] this IQueryable source, [CanBe #endregion #region Distinct - private static readonly MethodInfo _distinct = GetMethod(nameof(Queryable.Distinct)); + private static readonly MethodInfo _distinct = QueryableMethodFinder.GetMethod(nameof(Queryable.Distinct)); /// /// Returns distinct elements from a sequence by using the default equality comparer to compare values. @@ -511,7 +512,7 @@ public static IQueryable Distinct([NotNull] this IQueryable source) #endregion Distinct #region First - private static readonly MethodInfo _first = GetMethod(nameof(Queryable.First)); + private static readonly MethodInfo _first = QueryableMethodFinder.GetMethod(nameof(Queryable.First)); /// /// Returns the first element of a sequence. @@ -529,7 +530,7 @@ public static dynamic First([NotNull] this IQueryable source) return Execute(_first, source); } - private static readonly MethodInfo _firstPredicate = GetMethod(nameof(Queryable.First), 1); + private static readonly MethodInfo _firstPredicate = QueryableMethodFinder.GetMethod(nameof(Queryable.First), 1); /// /// Returns the first element of a sequence that satisfies a specified condition. @@ -584,7 +585,8 @@ public static dynamic First([NotNull] this IQueryable source, [NotNull] LambdaEx #endregion First #region FirstOrDefault - private static readonly MethodInfo _firstOrDefault = GetMethod(nameof(Queryable.FirstOrDefault)); + private static readonly MethodInfo _firstOrDefault = QueryableMethodFinder.GetMethod(nameof(Queryable.FirstOrDefault)); + private static readonly MethodInfo _firstOrDefaultPredicate = QueryableMethodFinder.GetMethodWithExpressionParameter(nameof(Queryable.FirstOrDefault)); /// /// Returns the first element of a sequence, or a default value if the sequence contains no elements. @@ -653,7 +655,6 @@ public static dynamic FirstOrDefault([NotNull] this IQueryable source, [NotNull] return Execute(_firstOrDefaultPredicate, source, lambda); } - private static readonly MethodInfo _firstOrDefaultPredicate = GetMethod(nameof(Queryable.FirstOrDefault), 1); #endregion FirstOrDefault #region GroupBy @@ -1079,7 +1080,9 @@ public static IQueryable Join([NotNull] this IQueryable /// Returns the last element of a sequence. /// @@ -1096,8 +1099,6 @@ public static dynamic Last([NotNull] this IQueryable source) return Execute(_last, source); } - private static readonly MethodInfo _lastPredicate = GetMethod(nameof(Queryable.Last), 1); - /// /// Returns the last element of a sequence that satisfies a specified condition. /// @@ -1151,7 +1152,9 @@ public static dynamic Last([NotNull] this IQueryable source, [NotNull] LambdaExp #endregion Last #region LastOrDefault - private static readonly MethodInfo _lastDefault = GetMethod(nameof(Queryable.LastOrDefault)); + private static readonly MethodInfo _lastDefault = QueryableMethodFinder.GetMethod(nameof(Queryable.LastOrDefault)); + private static readonly MethodInfo _lastDefaultPredicate = QueryableMethodFinder.GetMethodWithExpressionParameter(nameof(Queryable.LastOrDefault)); + /// /// Returns the last element of a sequence, or a default value if the sequence contains no elements. /// @@ -1168,8 +1171,6 @@ public static dynamic LastOrDefault([NotNull] this IQueryable source) return Execute(_lastDefault, source); } - private static readonly MethodInfo _lastDefaultPredicate = GetMethod(nameof(Queryable.LastOrDefault), 1); - /// /// Returns the last element of a sequence that satisfies a specified condition, or a default value if the sequence contains no elements. /// @@ -1222,7 +1223,8 @@ public static dynamic LastOrDefault([NotNull] this IQueryable source, [NotNull] #endregion LastOrDefault #region LongCount - private static readonly MethodInfo _longCount = GetMethod(nameof(Queryable.LongCount)); + private static readonly MethodInfo _longCount = QueryableMethodFinder.GetMethod(nameof(Queryable.LongCount)); + private static readonly MethodInfo _longCountPredicate = QueryableMethodFinder.GetMethodWithExpressionParameter(nameof(Queryable.LongCount)); /// /// Returns the number of elements in a sequence. @@ -1242,8 +1244,6 @@ public static long LongCount([NotNull] this IQueryable source) return Execute(_longCount, source); } - private static readonly MethodInfo _longCountPredicate = GetMethod(nameof(Queryable.LongCount), 1); - /// /// Returns the number of elements in a sequence. /// @@ -1295,7 +1295,8 @@ public static long LongCount([NotNull] this IQueryable source, [NotNull] LambdaE #endregion LongCount #region Max - private static readonly MethodInfo _max = GetMethod(nameof(Queryable.Max)); + private static readonly MethodInfo _max = QueryableMethodFinder.GetMethod(nameof(Queryable.Max)); + private static readonly MethodInfo _maxPredicate = QueryableMethodFinder.GetMethodWithExpressionParameter(nameof(Queryable.Max)); /// /// Computes the max element of a sequence. @@ -1317,8 +1318,6 @@ public static object Max([NotNull] this IQueryable source) return Execute(_max, source); } - private static readonly MethodInfo _maxPredicate = GetMethod(nameof(Queryable.Max), 1); - /// /// Computes the max element of a sequence. /// @@ -1368,7 +1367,8 @@ public static object Max([NotNull] this IQueryable source, [NotNull] LambdaExpre #endregion Max #region Min - private static readonly MethodInfo _min = GetMethod(nameof(Queryable.Min)); + private static readonly MethodInfo _min = QueryableMethodFinder.GetMethod(nameof(Queryable.Min)); + private static readonly MethodInfo _minPredicate = QueryableMethodFinder.GetMethodWithExpressionParameter(nameof(Queryable.Min)); /// /// Computes the min element of a sequence. @@ -1390,8 +1390,6 @@ public static object Min([NotNull] this IQueryable source) return Execute(_min, source); } - private static readonly MethodInfo _minPredicate = GetMethod(nameof(Queryable.Min), 1); - /// /// Computes the min element of a sequence. /// @@ -1441,7 +1439,7 @@ public static object Min([NotNull] this IQueryable source, [NotNull] LambdaExpre #endregion Min #region OfType - private static readonly MethodInfo _ofType = GetGenericMethod(nameof(Queryable.OfType)); + private static readonly MethodInfo _ofType = QueryableMethodFinder.GetGenericMethod(nameof(Queryable.OfType)); /// /// Filters the elements of an based on a specified type. @@ -2104,6 +2102,9 @@ public static IQueryable SelectMany([NotNull] this IQueryable source, [NotNull] #endregion SelectMany #region Single/SingleOrDefault + private static readonly MethodInfo _singlePredicate = QueryableMethodFinder.GetMethodWithExpressionParameter(nameof(Queryable.Single)); + private static readonly MethodInfo _singleDefaultPredicate = QueryableMethodFinder.GetMethodWithExpressionParameter(nameof(Queryable.SingleOrDefault)); + /// /// Returns the only element of a sequence, and throws an exception if there /// is not exactly one element in the sequence. @@ -2122,8 +2123,6 @@ public static dynamic Single([NotNull] this IQueryable source) return source.Provider.Execute(optimized); } - private static readonly MethodInfo _singlePredicate = GetMethod(nameof(Queryable.Single), 1); - /// /// Returns the only element of a sequence that satisfies a specified condition, and throws an exception if there /// is not exactly one element in the sequence. @@ -2195,8 +2194,6 @@ public static dynamic SingleOrDefault([NotNull] this IQueryable source) return source.Provider.Execute(optimized); } - private static readonly MethodInfo _singleDefaultPredicate = GetMethod(nameof(Queryable.SingleOrDefault), 1); - /// /// Returns the only element of a sequence that satisfies a specified condition or a default value if the sequence /// is empty; and throws an exception if there is not exactly one element in the sequence. @@ -2253,7 +2250,7 @@ public static dynamic SingleOrDefault([NotNull] this IQueryable source, [NotNull #endregion Single/SingleOrDefault #region Skip - private static readonly MethodInfo _skip = GetMethod(nameof(Queryable.Skip), 1); + private static readonly MethodInfo _skip = QueryableMethodFinder.GetMethod(nameof(Queryable.Skip), 1); /// /// Bypasses a specified number of elements in a sequence and then returns the remaining elements. @@ -2275,15 +2272,7 @@ public static IQueryable Skip([NotNull] this IQueryable source, int count) #endregion Skip #region SkipWhile - - private static readonly MethodInfo _skipWhilePredicate = GetMethod(nameof(Queryable.SkipWhile), 1, mi => - { - return mi.GetParameters().Length == 2 && - mi.GetParameters()[1].ParameterType.GetTypeInfo().IsGenericType && - mi.GetParameters()[1].ParameterType.GetGenericTypeDefinition() == typeof(Expression<>) && - mi.GetParameters()[1].ParameterType.GetGenericArguments()[0].GetTypeInfo().IsGenericType && - mi.GetParameters()[1].ParameterType.GetGenericArguments()[0].GetGenericTypeDefinition() == typeof(Func<,>); - }); + private static readonly MethodInfo _skipWhilePredicate = QueryableMethodFinder.GetMethodWithExpressionParameter(nameof(Queryable.SkipWhile)); /// /// Bypasses elements in a sequence as long as a specified condition is true and then returns the remaining elements. @@ -2317,7 +2306,6 @@ public static IQueryable SkipWhile([NotNull] this IQueryable source, [NotNull] s { return SkipWhile(source, ParsingConfig.Default, predicate, args); } - #endregion SkipWhile #region Sum @@ -2338,7 +2326,7 @@ public static object Sum([NotNull] this IQueryable source) { Check.NotNull(source, nameof(source)); - var sum = GetMethod(nameof(Queryable.Sum), source.ElementType); + var sum = QueryableMethodFinder.GetMethod(nameof(Queryable.Sum), source.ElementType); return Execute(sum, source); } @@ -2366,7 +2354,7 @@ public static object Sum([NotNull] this IQueryable source, [NotNull] ParsingConf bool createParameterCtor = SupportsLinqToObjects(config, source); LambdaExpression lambda = DynamicExpressionParser.ParseLambda(config, createParameterCtor, source.ElementType, null, predicate, args); - var sumSelector = GetMethod(nameof(Queryable.Sum), lambda.GetReturnType(), 1); + var sumSelector = QueryableMethodFinder.GetMethod(nameof(Queryable.Sum), lambda.GetReturnType(), 1); return Execute(sumSelector, source, lambda); } @@ -2390,14 +2378,14 @@ public static object Sum([NotNull] this IQueryable source, [NotNull] LambdaExpre Check.NotNull(source, nameof(source)); Check.NotNull(lambda, nameof(lambda)); - var sumSelector = GetMethod(nameof(Queryable.Sum), lambda.GetReturnType(), 1); + var sumSelector = QueryableMethodFinder.GetMethod(nameof(Queryable.Sum), lambda.GetReturnType(), 1); return Execute(sumSelector, source, lambda); } #endregion Sum #region Take - private static readonly MethodInfo _take = GetMethod(nameof(Queryable.Take), 1); + private static readonly MethodInfo _take = QueryableMethodFinder.GetMethodWithIntParameter(nameof(Queryable.Take)); /// /// Returns a specified number of contiguous elements from the start of a sequence. /// @@ -2414,15 +2402,7 @@ public static IQueryable Take([NotNull] this IQueryable source, int count) #endregion Take #region TakeWhile - - private static readonly MethodInfo _takeWhilePredicate = GetMethod(nameof(Queryable.TakeWhile), 1, mi => - { - return mi.GetParameters().Length == 2 && - mi.GetParameters()[1].ParameterType.GetTypeInfo().IsGenericType && - mi.GetParameters()[1].ParameterType.GetGenericTypeDefinition() == typeof(Expression<>) && - mi.GetParameters()[1].ParameterType.GetGenericArguments()[0].GetTypeInfo().IsGenericType && - mi.GetParameters()[1].ParameterType.GetGenericArguments()[0].GetGenericTypeDefinition() == typeof(Func<,>); - }); + private static readonly MethodInfo _takeWhilePredicate = QueryableMethodFinder.GetMethodWithExpressionParameter(nameof(Queryable.TakeWhile)); /// /// Returns elements from a sequence as long as a specified condition is true. @@ -2693,7 +2673,6 @@ public static IQueryable Where([NotNull] this IQueryable(MethodInfo operatorMethodInfo, IQueryabl return (TResult)Convert.ChangeType(result, typeof(TResult)); } - - private static object Execute(MethodInfo operatorMethodInfo, IQueryable source, LambdaExpression expression) - => Execute(operatorMethodInfo, source, Expression.Quote(expression)); + private static object Execute(MethodInfo operatorMethodInfo, IQueryable source, LambdaExpression expression) => + Execute(operatorMethodInfo, source, Expression.Quote(expression)); private static object Execute(MethodInfo operatorMethodInfo, IQueryable source, Expression expression) { @@ -2802,29 +2780,7 @@ private static TResult Execute(MethodInfo operatorMethodInfo, IQueryabl return (TResult)Convert.ChangeType(result, typeof(TResult)); } - private static MethodInfo GetGenericMethod(string name) - { - return typeof(Queryable).GetTypeInfo().GetDeclaredMethods(name).Single(mi => mi.IsGenericMethod); - } - - private static MethodInfo GetMethod(string name, Type argumentType, Type returnType, int parameterCount = 0, Func predicate = null) => - GetMethod(name, returnType, parameterCount, mi => mi.ToString().Contains(argumentType.ToString()) && ((predicate == null) || predicate(mi))); - - private static MethodInfo GetMethod(string name, Type returnType, int parameterCount = 0, Func predicate = null) => - GetMethod(name, parameterCount, mi => (mi.ReturnType == returnType) && ((predicate == null) || predicate(mi))); - private static MethodInfo GetMethod(string name, int parameterCount = 0, Func predicate = null) - { - try - { - return typeof(Queryable).GetTypeInfo().GetDeclaredMethods(name).Single(mi => - mi.GetParameters().Length == parameterCount + 1 && (predicate == null || predicate(mi))); - } - catch (Exception ex) - { - throw new Exception("Specific method not found: " + name, ex); - } - } #endregion Private Helpers } } diff --git a/src/System.Linq.Dynamic.Core/Util/QueryableMethodFinder.cs b/src/System.Linq.Dynamic.Core/Util/QueryableMethodFinder.cs new file mode 100644 index 00000000..69b93247 --- /dev/null +++ b/src/System.Linq.Dynamic.Core/Util/QueryableMethodFinder.cs @@ -0,0 +1,47 @@ +using System.Linq.Expressions; +using System.Reflection; + +namespace System.Linq.Dynamic.Core.Util +{ + internal static class QueryableMethodFinder + { + public static MethodInfo GetGenericMethod(string name) + { + return typeof(Queryable).GetTypeInfo().GetDeclaredMethods(name).Single(mi => mi.IsGenericMethod); + } + + public static MethodInfo GetMethod(string name, Type argumentType, Type returnType, int parameterCount = 0, Func predicate = null) => + GetMethod(name, returnType, parameterCount, mi => mi.ToString().Contains(argumentType.ToString()) && ((predicate == null) || predicate(mi))); + + public static MethodInfo GetMethod(string name, Type returnType, int parameterCount = 0, Func predicate = null) => + GetMethod(name, parameterCount, mi => (mi.ReturnType == returnType) && ((predicate == null) || predicate(mi))); + + public static MethodInfo GetMethodWithExpressionParameter(string name) => + GetMethod(name, 1, mi => + mi.GetParameters().Length == 2 && + mi.GetParameters()[1].ParameterType.GetTypeInfo().IsGenericType && + mi.GetParameters()[1].ParameterType.GetGenericTypeDefinition() == typeof(Expression<>) && + mi.GetParameters()[1].ParameterType.GetGenericArguments()[0].GetTypeInfo().IsGenericType && + mi.GetParameters()[1].ParameterType.GetGenericArguments()[0].GetGenericTypeDefinition() == typeof(Func<,>) + ); + + public static MethodInfo GetMethodWithIntParameter(string name) => + GetMethod(name, 1, mi => + mi.GetParameters().Length == 2 && + mi.GetParameters()[1].ParameterType == typeof(int) + ); + + public static MethodInfo GetMethod(string name, int parameterCount = 0, Func predicate = null) + { + try + { + return typeof(Queryable).GetTypeInfo().GetDeclaredMethods(name).Single(mi => + mi.GetParameters().Length == parameterCount + 1 && (predicate == null || predicate(mi))); + } + catch (Exception ex) + { + throw new Exception("Specific method not found: " + name, ex); + } + } + } +} diff --git a/version.xml b/version.xml index 14aba62d..8f6e63f0 100644 --- a/version.xml +++ b/version.xml @@ -1,5 +1,5 @@ - 11 + 12-preview-01