FileContextCore/Query/Internal/FileContextLinqOperatorProvider.cs
// Copyright (c) morrisjdev. All rights reserved.
// Original copyright (c) .NET Foundation. All rights reserved.
// Modified version by morrisjdev
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.EntityFrameworkCore.Utilities;
namespace FileContextCore.Query.Internal
{
public static class FileContextLinqOperatorProvider
{
public static MethodInfo AsEnumerable { get; }
public static MethodInfo Cast { get; }
public static MethodInfo OfType { get; }
public static MethodInfo All { get; }
public static MethodInfo AnyWithoutPredicate { get; }
public static MethodInfo AnyWithPredicate { get; }
public static MethodInfo Contains { get; }
public static MethodInfo Concat { get; }
public static MethodInfo Except { get; }
public static MethodInfo Intersect { get; }
public static MethodInfo Union { get; }
public static MethodInfo CountWithoutPredicate { get; }
public static MethodInfo CountWithPredicate { get; }
public static MethodInfo LongCountWithoutPredicate { get; }
public static MethodInfo LongCountWithPredicate { get; }
public static MethodInfo MinWithSelector { get; }
public static MethodInfo MinWithoutSelector { get; }
public static MethodInfo MaxWithSelector { get; }
public static MethodInfo MaxWithoutSelector { get; }
public static MethodInfo ElementAt { get; }
public static MethodInfo ElementAtOrDefault { get; }
public static MethodInfo FirstWithoutPredicate { get; }
public static MethodInfo FirstWithPredicate { get; }
public static MethodInfo FirstOrDefaultWithoutPredicate { get; }
public static MethodInfo FirstOrDefaultWithPredicate { get; }
public static MethodInfo SingleWithoutPredicate { get; }
public static MethodInfo SingleWithPredicate { get; }
public static MethodInfo SingleOrDefaultWithoutPredicate { get; }
public static MethodInfo SingleOrDefaultWithPredicate { get; }
public static MethodInfo LastWithoutPredicate { get; }
public static MethodInfo LastWithPredicate { get; }
public static MethodInfo LastOrDefaultWithoutPredicate { get; }
public static MethodInfo LastOrDefaultWithPredicate { get; }
public static MethodInfo Distinct { get; }
public static MethodInfo Reverse { get; }
public static MethodInfo Where { get; }
public static MethodInfo Select { get; }
public static MethodInfo Skip { get; }
public static MethodInfo Take { get; }
public static MethodInfo SkipWhile { get; }
public static MethodInfo TakeWhile { get; }
public static MethodInfo OrderBy { get; }
public static MethodInfo OrderByDescending { get; }
public static MethodInfo ThenBy { get; }
public static MethodInfo ThenByDescending { get; }
public static MethodInfo DefaultIfEmptyWithoutArgument { get; }
public static MethodInfo DefaultIfEmptyWithArgument { get; }
public static MethodInfo Join { get; }
public static MethodInfo GroupJoin { get; }
public static MethodInfo SelectManyWithCollectionSelector { get; }
public static MethodInfo SelectManyWithoutCollectionSelector { get; }
public static MethodInfo GroupByWithKeySelector { get; }
public static MethodInfo GroupByWithKeyElementSelector { get; }
public static MethodInfo GroupByWithKeyElementResultSelector { get; }
public static MethodInfo GroupByWithKeyResultSelector { get; }
public static MethodInfo GetAverageWithoutSelector(Type type) => AverageWithoutSelectorMethods[type];
public static MethodInfo GetAverageWithSelector(Type type) => AverageWithSelectorMethods[type];
public static MethodInfo GetMaxWithoutSelector(Type type)
=> MaxWithoutSelectorMethods.TryGetValue(type, out var method)
? method
: MaxWithoutSelector;
public static MethodInfo GetMaxWithSelector(Type type)
=> MaxWithSelectorMethods.TryGetValue(type, out var method)
? method
: MaxWithSelector;
public static MethodInfo GetMinWithoutSelector(Type type)
=> MinWithoutSelectorMethods.TryGetValue(type, out var method)
? method
: MinWithoutSelector;
public static MethodInfo GetMinWithSelector(Type type)
=> MinWithSelectorMethods.TryGetValue(type, out var method)
? method
: MinWithSelector;
public static MethodInfo GetSumWithoutSelector(Type type) => SumWithoutSelectorMethods[type];
public static MethodInfo GetSumWithSelector(Type type) => SumWithSelectorMethods[type];
private static Dictionary<Type, MethodInfo> AverageWithoutSelectorMethods { get; }
private static Dictionary<Type, MethodInfo> AverageWithSelectorMethods { get; }
private static Dictionary<Type, MethodInfo> MaxWithoutSelectorMethods { get; }
private static Dictionary<Type, MethodInfo> MaxWithSelectorMethods { get; }
private static Dictionary<Type, MethodInfo> MinWithoutSelectorMethods { get; }
private static Dictionary<Type, MethodInfo> MinWithSelectorMethods { get; }
private static Dictionary<Type, MethodInfo> SumWithoutSelectorMethods { get; }
private static Dictionary<Type, MethodInfo> SumWithSelectorMethods { get; }
private static Type GetFuncType(int funcGenericArguments)
{
return funcGenericArguments switch
{
1 => typeof(Func<>),
2 => typeof(Func<,>),
3 => typeof(Func<,,>),
4 => typeof(Func<,,,>),
_ => throw new InvalidOperationException("Invalid number of arguments for Func"),
};
}
private static bool IsFunc(Type type, int funcGenericArguments = 2)
=> type.IsGenericType
&& type.GetGenericTypeDefinition() == GetFuncType(funcGenericArguments);
static FileContextLinqOperatorProvider()
{
var enumerableMethods = typeof(Enumerable).GetTypeInfo()
.GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly).ToList();
AsEnumerable = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.AsEnumerable) && mi.IsGenericMethod && mi.GetParameters().Length == 1);
Cast = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.Cast) && mi.GetParameters().Length == 1);
OfType = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.OfType) && mi.GetParameters().Length == 1);
All = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.All) && mi.GetParameters().Length == 2 && IsFunc(mi.GetParameters()[1].ParameterType));
AnyWithoutPredicate = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.Any) && mi.GetParameters().Length == 1);
AnyWithPredicate = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.Any) && mi.GetParameters().Length == 2 && IsFunc(mi.GetParameters()[1].ParameterType));
Contains = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.Contains) && mi.GetParameters().Length == 2);
Concat = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.Concat) && mi.GetParameters().Length == 2);
Except = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.Except) && mi.GetParameters().Length == 2);
Intersect = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.Intersect) && mi.GetParameters().Length == 2);
Union = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.Union) && mi.GetParameters().Length == 2);
CountWithoutPredicate = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.Count) && mi.GetParameters().Length == 1);
CountWithPredicate = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.Count) && mi.GetParameters().Length == 2 && IsFunc(mi.GetParameters()[1].ParameterType));
LongCountWithoutPredicate = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.LongCount) && mi.GetParameters().Length == 1);
LongCountWithPredicate = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.LongCount) && mi.GetParameters().Length == 2 && IsFunc(mi.GetParameters()[1].ParameterType));
MinWithSelector = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.Min) && mi.IsGenericMethod && mi.GetGenericArguments().Length == 2 && mi.GetParameters().Length == 2 && IsFunc(mi.GetParameters()[1].ParameterType));
MinWithoutSelector = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.Min) && mi.IsGenericMethod && mi.GetGenericArguments().Length == 1 && mi.GetParameters().Length == 1);
MaxWithSelector = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.Max) && mi.IsGenericMethod && mi.GetGenericArguments().Length == 2 && mi.GetParameters().Length == 2 && IsFunc(mi.GetParameters()[1].ParameterType));
MaxWithoutSelector = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.Max) && mi.IsGenericMethod && mi.GetGenericArguments().Length == 1 && mi.GetParameters().Length == 1);
ElementAt = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.ElementAt) && mi.GetParameters().Length == 2);
ElementAtOrDefault = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.ElementAtOrDefault) && mi.GetParameters().Length == 2);
FirstWithoutPredicate = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.First) && mi.GetParameters().Length == 1);
FirstWithPredicate = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.First) && mi.GetParameters().Length == 2 && IsFunc(mi.GetParameters()[1].ParameterType));
FirstOrDefaultWithoutPredicate = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.FirstOrDefault) && mi.GetParameters().Length == 1);
FirstOrDefaultWithPredicate = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.FirstOrDefault) && mi.GetParameters().Length == 2 && IsFunc(mi.GetParameters()[1].ParameterType));
SingleWithoutPredicate = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.Single) && mi.GetParameters().Length == 1);
SingleWithPredicate = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.Single) && mi.GetParameters().Length == 2 && IsFunc(mi.GetParameters()[1].ParameterType));
SingleOrDefaultWithoutPredicate = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.SingleOrDefault) && mi.GetParameters().Length == 1);
SingleOrDefaultWithPredicate = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.SingleOrDefault) && mi.GetParameters().Length == 2 && IsFunc(mi.GetParameters()[1].ParameterType));
LastWithoutPredicate = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.Last) && mi.GetParameters().Length == 1);
LastWithPredicate = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.Last) && mi.GetParameters().Length == 2 && IsFunc(mi.GetParameters()[1].ParameterType));
LastOrDefaultWithoutPredicate = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.LastOrDefault) && mi.GetParameters().Length == 1);
LastOrDefaultWithPredicate = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.LastOrDefault) && mi.GetParameters().Length == 2 && IsFunc(mi.GetParameters()[1].ParameterType));
Distinct = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.Distinct) && mi.GetParameters().Length == 1);
Reverse = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.Reverse) && mi.GetParameters().Length == 1);
Where = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.Where) && mi.GetParameters().Length == 2 && IsFunc(mi.GetParameters()[1].ParameterType));
Select = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.Select) && mi.GetParameters().Length == 2 && IsFunc(mi.GetParameters()[1].ParameterType));
Skip = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.Skip) && mi.GetParameters().Length == 2);
Take = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.Take) && mi.GetParameters().Length == 2);
SkipWhile = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.SkipWhile) && mi.GetParameters().Length == 2 && IsFunc(mi.GetParameters()[1].ParameterType));
TakeWhile = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.TakeWhile) && mi.GetParameters().Length == 2 && IsFunc(mi.GetParameters()[1].ParameterType));
OrderBy = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.OrderBy) && mi.GetParameters().Length == 2 && IsFunc(mi.GetParameters()[1].ParameterType));
OrderByDescending = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.OrderByDescending) && mi.GetParameters().Length == 2 && IsFunc(mi.GetParameters()[1].ParameterType));
ThenBy = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.ThenBy) && mi.GetParameters().Length == 2 && IsFunc(mi.GetParameters()[1].ParameterType));
ThenByDescending = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.ThenByDescending) && mi.GetParameters().Length == 2 && IsFunc(mi.GetParameters()[1].ParameterType));
DefaultIfEmptyWithoutArgument = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.DefaultIfEmpty) && mi.GetParameters().Length == 1);
DefaultIfEmptyWithArgument = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.DefaultIfEmpty) && mi.GetParameters().Length == 2);
Join = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.Join) && mi.GetParameters().Length == 5);
GroupJoin = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.GroupJoin) && mi.GetParameters().Length == 5);
SelectManyWithCollectionSelector = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.SelectMany) && mi.GetParameters().Length == 3 && IsFunc(mi.GetParameters()[1].ParameterType));
SelectManyWithoutCollectionSelector = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.SelectMany) && mi.GetParameters().Length == 2 && IsFunc(mi.GetParameters()[1].ParameterType));
GroupByWithKeySelector = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.GroupBy) && mi.GetParameters().Length == 2 && IsFunc(mi.GetParameters()[1].ParameterType));
GroupByWithKeyElementSelector = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.GroupBy) && mi.GetParameters().Length == 3 && IsFunc(mi.GetParameters()[1].ParameterType) && IsFunc(mi.GetParameters()[2].ParameterType));
GroupByWithKeyElementResultSelector = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.GroupBy) && mi.GetParameters().Length == 4 && IsFunc(mi.GetParameters()[1].ParameterType) && IsFunc(mi.GetParameters()[2].ParameterType) && IsFunc(mi.GetParameters()[3].ParameterType, 3));
GroupByWithKeyResultSelector = enumerableMethods.Single(
mi => mi.Name == nameof(Enumerable.GroupBy) && mi.GetParameters().Length == 3 && IsFunc(mi.GetParameters()[1].ParameterType) && IsFunc(mi.GetParameters()[2].ParameterType, 3));
MethodInfo getSumOrAverageWithoutSelector<T>(string methodName)
=> enumerableMethods.Single(
mi => mi.Name == methodName
&& mi.GetParameters().Length == 1
&& mi.GetParameters()[0].ParameterType.GetGenericArguments()[0] == typeof(T));
static bool hasSelector<T>(Type type)
=> type.IsGenericType
&& type.GetGenericArguments().Length == 2
&& type.GetGenericArguments()[1] == typeof(T);
MethodInfo getSumOrAverageWithSelector<T>(string methodName)
=> enumerableMethods.Single(
mi => mi.Name == methodName
&& mi.GetParameters().Length == 2
&& hasSelector<T>(mi.GetParameters()[1].ParameterType));
AverageWithoutSelectorMethods = new Dictionary<Type, MethodInfo>
{
{ typeof(decimal), getSumOrAverageWithoutSelector<decimal>(nameof(Queryable.Average)) },
{ typeof(long), getSumOrAverageWithoutSelector<long>(nameof(Queryable.Average)) },
{ typeof(int), getSumOrAverageWithoutSelector<int>(nameof(Queryable.Average)) },
{ typeof(double), getSumOrAverageWithoutSelector<double>(nameof(Queryable.Average)) },
{ typeof(float), getSumOrAverageWithoutSelector<float>(nameof(Queryable.Average)) },
{ typeof(decimal?), getSumOrAverageWithoutSelector<decimal?>(nameof(Queryable.Average)) },
{ typeof(long?), getSumOrAverageWithoutSelector<long?>(nameof(Queryable.Average)) },
{ typeof(int?), getSumOrAverageWithoutSelector<int?>(nameof(Queryable.Average)) },
{ typeof(double?), getSumOrAverageWithoutSelector<double?>(nameof(Queryable.Average)) },
{ typeof(float?), getSumOrAverageWithoutSelector<float?>(nameof(Queryable.Average)) }
};
AverageWithSelectorMethods = new Dictionary<Type, MethodInfo>
{
{ typeof(decimal), getSumOrAverageWithSelector<decimal>(nameof(Queryable.Average)) },
{ typeof(long), getSumOrAverageWithSelector<long>(nameof(Queryable.Average)) },
{ typeof(int), getSumOrAverageWithSelector<int>(nameof(Queryable.Average)) },
{ typeof(double), getSumOrAverageWithSelector<double>(nameof(Queryable.Average)) },
{ typeof(float), getSumOrAverageWithSelector<float>(nameof(Queryable.Average)) },
{ typeof(decimal?), getSumOrAverageWithSelector<decimal?>(nameof(Queryable.Average)) },
{ typeof(long?), getSumOrAverageWithSelector<long?>(nameof(Queryable.Average)) },
{ typeof(int?), getSumOrAverageWithSelector<int?>(nameof(Queryable.Average)) },
{ typeof(double?), getSumOrAverageWithSelector<double?>(nameof(Queryable.Average)) },
{ typeof(float?), getSumOrAverageWithSelector<float?>(nameof(Queryable.Average)) }
};
MaxWithoutSelectorMethods = new Dictionary<Type, MethodInfo>
{
{ typeof(decimal), getSumOrAverageWithoutSelector<decimal>(nameof(Queryable.Max)) },
{ typeof(long), getSumOrAverageWithoutSelector<long>(nameof(Queryable.Max)) },
{ typeof(int), getSumOrAverageWithoutSelector<int>(nameof(Queryable.Max)) },
{ typeof(double), getSumOrAverageWithoutSelector<double>(nameof(Queryable.Max)) },
{ typeof(float), getSumOrAverageWithoutSelector<float>(nameof(Queryable.Max)) },
{ typeof(decimal?), getSumOrAverageWithoutSelector<decimal?>(nameof(Queryable.Max)) },
{ typeof(long?), getSumOrAverageWithoutSelector<long?>(nameof(Queryable.Max)) },
{ typeof(int?), getSumOrAverageWithoutSelector<int?>(nameof(Queryable.Max)) },
{ typeof(double?), getSumOrAverageWithoutSelector<double?>(nameof(Queryable.Max)) },
{ typeof(float?), getSumOrAverageWithoutSelector<float?>(nameof(Queryable.Max)) }
};
MaxWithSelectorMethods = new Dictionary<Type, MethodInfo>
{
{ typeof(decimal), getSumOrAverageWithSelector<decimal>(nameof(Queryable.Max)) },
{ typeof(long), getSumOrAverageWithSelector<long>(nameof(Queryable.Max)) },
{ typeof(int), getSumOrAverageWithSelector<int>(nameof(Queryable.Max)) },
{ typeof(double), getSumOrAverageWithSelector<double>(nameof(Queryable.Max)) },
{ typeof(float), getSumOrAverageWithSelector<float>(nameof(Queryable.Max)) },
{ typeof(decimal?), getSumOrAverageWithSelector<decimal?>(nameof(Queryable.Max)) },
{ typeof(long?), getSumOrAverageWithSelector<long?>(nameof(Queryable.Max)) },
{ typeof(int?), getSumOrAverageWithSelector<int?>(nameof(Queryable.Max)) },
{ typeof(double?), getSumOrAverageWithSelector<double?>(nameof(Queryable.Max)) },
{ typeof(float?), getSumOrAverageWithSelector<float?>(nameof(Queryable.Max)) }
};
MinWithoutSelectorMethods = new Dictionary<Type, MethodInfo>
{
{ typeof(decimal), getSumOrAverageWithoutSelector<decimal>(nameof(Queryable.Min)) },
{ typeof(long), getSumOrAverageWithoutSelector<long>(nameof(Queryable.Min)) },
{ typeof(int), getSumOrAverageWithoutSelector<int>(nameof(Queryable.Min)) },
{ typeof(double), getSumOrAverageWithoutSelector<double>(nameof(Queryable.Min)) },
{ typeof(float), getSumOrAverageWithoutSelector<float>(nameof(Queryable.Min)) },
{ typeof(decimal?), getSumOrAverageWithoutSelector<decimal?>(nameof(Queryable.Min)) },
{ typeof(long?), getSumOrAverageWithoutSelector<long?>(nameof(Queryable.Min)) },
{ typeof(int?), getSumOrAverageWithoutSelector<int?>(nameof(Queryable.Min)) },
{ typeof(double?), getSumOrAverageWithoutSelector<double?>(nameof(Queryable.Min)) },
{ typeof(float?), getSumOrAverageWithoutSelector<float?>(nameof(Queryable.Min)) }
};
MinWithSelectorMethods = new Dictionary<Type, MethodInfo>
{
{ typeof(decimal), getSumOrAverageWithSelector<decimal>(nameof(Queryable.Min)) },
{ typeof(long), getSumOrAverageWithSelector<long>(nameof(Queryable.Min)) },
{ typeof(int), getSumOrAverageWithSelector<int>(nameof(Queryable.Min)) },
{ typeof(double), getSumOrAverageWithSelector<double>(nameof(Queryable.Min)) },
{ typeof(float), getSumOrAverageWithSelector<float>(nameof(Queryable.Min)) },
{ typeof(decimal?), getSumOrAverageWithSelector<decimal?>(nameof(Queryable.Min)) },
{ typeof(long?), getSumOrAverageWithSelector<long?>(nameof(Queryable.Min)) },
{ typeof(int?), getSumOrAverageWithSelector<int?>(nameof(Queryable.Min)) },
{ typeof(double?), getSumOrAverageWithSelector<double?>(nameof(Queryable.Min)) },
{ typeof(float?), getSumOrAverageWithSelector<float?>(nameof(Queryable.Min)) }
};
SumWithoutSelectorMethods = new Dictionary<Type, MethodInfo>
{
{ typeof(decimal), getSumOrAverageWithoutSelector<decimal>(nameof(Queryable.Sum)) },
{ typeof(long), getSumOrAverageWithoutSelector<long>(nameof(Queryable.Sum)) },
{ typeof(int), getSumOrAverageWithoutSelector<int>(nameof(Queryable.Sum)) },
{ typeof(double), getSumOrAverageWithoutSelector<double>(nameof(Queryable.Sum)) },
{ typeof(float), getSumOrAverageWithoutSelector<float>(nameof(Queryable.Sum)) },
{ typeof(decimal?), getSumOrAverageWithoutSelector<decimal?>(nameof(Queryable.Sum)) },
{ typeof(long?), getSumOrAverageWithoutSelector<long?>(nameof(Queryable.Sum)) },
{ typeof(int?), getSumOrAverageWithoutSelector<int?>(nameof(Queryable.Sum)) },
{ typeof(double?), getSumOrAverageWithoutSelector<double?>(nameof(Queryable.Sum)) },
{ typeof(float?), getSumOrAverageWithoutSelector<float?>(nameof(Queryable.Sum)) }
};
SumWithSelectorMethods = new Dictionary<Type, MethodInfo>
{
{ typeof(decimal), getSumOrAverageWithSelector<decimal>(nameof(Queryable.Sum)) },
{ typeof(long), getSumOrAverageWithSelector<long>(nameof(Queryable.Sum)) },
{ typeof(int), getSumOrAverageWithSelector<int>(nameof(Queryable.Sum)) },
{ typeof(double), getSumOrAverageWithSelector<double>(nameof(Queryable.Sum)) },
{ typeof(float), getSumOrAverageWithSelector<float>(nameof(Queryable.Sum)) },
{ typeof(decimal?), getSumOrAverageWithSelector<decimal?>(nameof(Queryable.Sum)) },
{ typeof(long?), getSumOrAverageWithSelector<long?>(nameof(Queryable.Sum)) },
{ typeof(int?), getSumOrAverageWithSelector<int?>(nameof(Queryable.Sum)) },
{ typeof(double?), getSumOrAverageWithSelector<double?>(nameof(Queryable.Sum)) },
{ typeof(float?), getSumOrAverageWithSelector<float?>(nameof(Queryable.Sum)) }
};
}
}
}