Back to OIM Explorer

DevExpress.Data.v24.2/DevExpress.Data.ODataLinq.Helpers/ODataLinqHelpers.cs

Decompiler Source FileDevExpress.Data.v24.2.ODataLinqHelpersDecompiled Source

4 extracted method/event/call references in ODataLinqHelpers.

Source: F:\Claude\.tmp\oim-decompiled-full\0336_One_Identity_Manager_DevExpress.Data.v24.2.dll\DevExpress.Data.ODataLinq.Helpers\ODataLinqHelpers.cs

Source size: 32.444 characters

Interpretation

  • Decompiled source file. Use method/event registrations and call-site extraction to connect back to DialogMethod, QBMEvent, and API layers.

Relations

  • CallMethod: Max at line 596
  • CallMethod: Min at line 599
  • CallMethod: OrderBy at line 637
  • CallMethod: OrderBy at line 650

Typed Edges

  • No typed edges extracted for this source.

References

  • No direct source references extracted.

Referenced By

  • No direct source references extracted.

C# source-derived context

Generated by pattern extraction from the decompiled C# source and decompile index. This is factual source evidence, not inferred behavior.

None extracted.

Summary: classes ODataLinqHelpers, DataServiceQueryHelper, WrapperHelper, ListHelperBase; methods FitToSignature, GetResultSynchronously, GetCount, Create, CreateFromWrapper, CallMethod

Complete Source

C#773 lines
1using System;2using System.Collections;3using System.Collections.Generic;4using System.Linq;5using System.Linq.Expressions;6using System.Reflection;7using System.Threading;8using DevExpress.Data.Filtering;9using DevExpress.Data.Filtering.Helpers;10using DevExpress.Data.Helpers;11using DevExpress.Data.Internal;12using DevExpress.Data.Linq;1314namespace DevExpress.Data.ODataLinq.Helpers;1516public static class ODataLinqHelpers17{18	private sealed class DataServiceQueryHelper19	{20		private readonly Type dataServiceQueryType;2122		private readonly Func<object, string, object, object> addQueryOptionHandler;2324		private readonly Func<object, IEnumerable> executeQueryHandler;2526		private readonly Func<object, object> getContextHandler;2728		private readonly Func<object, object> getContinuationTokenHandler;2930		private readonly Func<object, object, IEnumerable> executeContextHandler;3132		private readonly Func<object, long> getCountHandler;3334		private readonly Func<object, object> includeCountHandler;3536		public DataServiceQueryHelper(Type dataServiceQueryType)37		{38			this.dataServiceQueryType = dataServiceQueryType;39			ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "q");40			UnaryExpression instanceExpression = Expression.Convert(parameterExpression, dataServiceQueryType);41			addQueryOptionHandler = BuildAddQueryHandler(dataServiceQueryType, parameterExpression, instanceExpression);42			executeQueryHandler = BuildExecuteQueryHandler(dataServiceQueryType, parameterExpression, instanceExpression);43			Type knownType = SafeTypeResolver.GetKnownType(dataServiceQueryType.Assembly, "Microsoft.OData.Client.QueryOperationResponse", throwOnError: true);44			getCountHandler = BuildGetCountHandler(parameterExpression, knownType);45			includeCountHandler = BuildIncludeCountHandler(dataServiceQueryType, parameterExpression, instanceExpression);46			getContinuationTokenHandler = BuildGetContinuationHandler(parameterExpression, knownType);47			getContextHandler = BuildGetContextHandler(dataServiceQueryType, parameterExpression, instanceExpression, out var contextProperty);48			executeContextHandler = BuildExecuteContextMethod(dataServiceQueryType, parameterExpression, contextProperty.PropertyType);49		}5051		private static Func<object, object, IEnumerable> BuildExecuteContextMethod(Type dataServiceQueryType, ParameterExpression instanceParameter, Type dataServiceContextType)52		{53			Type continuationAbstractType = SafeTypeResolver.GetKnownType(dataServiceQueryType.Assembly, "Microsoft.OData.Client.DataServiceQueryContinuation", throwOnError: true);54			MethodInfo methodInfo = (from mi in dataServiceContextType.GetMethods(BindingFlags.Instance | BindingFlags.Public)55				where mi.Name == "Execute" && FitToSignature(mi, continuationAbstractType)56				select mi).FirstOrDefault();57			if (methodInfo == null)58			{59				MethodInfo methodInfo2 = (from mi in dataServiceContextType.GetMethods(BindingFlags.Instance | BindingFlags.Public)60					where mi.Name == "ExecuteAsync" && FitToSignature(mi, continuationAbstractType)61					select mi).First();62				MethodInfo methodInfo3 = methodInfo2.MakeGenericMethod(dataServiceQueryType.GetGenericArguments());63				Type parameterType = methodInfo3.GetParameters()[0].ParameterType;64				ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "c");65				return Expression.Lambda<Func<object, object, IEnumerable>>(Expression.Convert(GetResultSynchronously(Expression.Call(Expression.Convert(instanceParameter, dataServiceContextType), methodInfo3, Expression.Convert(parameterExpression, parameterType))), typeof(IEnumerable)), new ParameterExpression[2] { instanceParameter, parameterExpression }).Compile();66			}67			MethodInfo methodInfo4 = methodInfo.MakeGenericMethod(dataServiceQueryType.GetGenericArguments());68			Type parameterType2 = methodInfo4.GetParameters()[0].ParameterType;69			ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object), "c");70			return Expression.Lambda<Func<object, object, IEnumerable>>(Expression.Convert(Expression.Call(Expression.Convert(instanceParameter, dataServiceContextType), methodInfo4, Expression.Convert(parameterExpression2, parameterType2)), typeof(IEnumerable)), new ParameterExpression[2] { instanceParameter, parameterExpression2 }).Compile();71		}7273		private static bool FitToSignature(MethodInfo mi, Type parameterType)74		{75			if (!mi.IsGenericMethod)76			{77				return false;78			}79			ParameterInfo[] parameters = mi.GetParameters();80			if (parameters.Length != 1)81			{82				return false;83			}84			return parameterType.IsAssignableFrom(parameters[0].ParameterType);85		}8687		private static Func<object, string, object, object> BuildAddQueryHandler(Type dataServiceQueryType, ParameterExpression instanceParameter, UnaryExpression instanceExpression)88		{89			ParameterExpression parameterExpression = Expression.Parameter(typeof(string), "name");90			ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object), "value");91			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy;92			MethodInfo method = dataServiceQueryType.GetMethod("AddQueryOption", bindingAttr, null, new Type[2]93			{94				typeof(string),95				typeof(object)96			}, null);97			return Expression.Lambda<Func<object, string, object, object>>(Expression.Convert(Expression.Call(instanceExpression, method, parameterExpression, parameterExpression2), typeof(object)), new ParameterExpression[3] { instanceParameter, parameterExpression, parameterExpression2 }).Compile();98		}99100		private static Func<object, IEnumerable> BuildExecuteQueryHandler(Type dataServiceQueryType, ParameterExpression instanceParameter, UnaryExpression instanceExpression)101		{102			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy;103			MethodInfo method = dataServiceQueryType.GetMethod("Execute", bindingAttr, null, Type.EmptyTypes, null);104			if (method != null)105			{106				return Expression.Lambda<Func<object, IEnumerable>>(Expression.Convert(Expression.Call(instanceExpression, method), typeof(IEnumerable)), new ParameterExpression[1] { instanceParameter }).Compile();107			}108			MethodInfo method2 = dataServiceQueryType.GetMethod("ExecuteAsync", bindingAttr, null, Type.EmptyTypes, null);109			return Expression.Lambda<Func<object, IEnumerable>>(Expression.Convert(GetResultSynchronously(Expression.Call(instanceExpression, method2)), typeof(IEnumerable)), new ParameterExpression[1] { instanceParameter }).Compile();110		}111112		private static Func<object, object> BuildGetContextHandler(Type dataServiceQueryType, ParameterExpression instanceParameter, UnaryExpression instanceExpression, out PropertyInfo contextProperty)113		{114			contextProperty = dataServiceQueryType.GetProperty("Context");115			return Expression.Lambda<Func<object, object>>(Expression.Convert(Expression.Property(instanceExpression, contextProperty), typeof(object)), new ParameterExpression[1] { instanceParameter }).Compile();116		}117118		private static Func<object, object> BuildGetContinuationHandler(ParameterExpression instanceParameter, Type executeResultType)119		{120			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy;121			MethodInfo method = executeResultType.GetMethod("GetContinuation", bindingAttr, null, Type.EmptyTypes, null);122			return Expression.Lambda<Func<object, object>>(Expression.Convert(Expression.Call(Expression.Convert(instanceParameter, executeResultType), method), typeof(object)), new ParameterExpression[1] { instanceParameter }).Compile();123		}124125		private static Func<object, object> BuildIncludeCountHandler(Type dataServiceQueryType, ParameterExpression instanceParameter, UnaryExpression instanceExpression)126		{127			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public;128			MethodInfo method = dataServiceQueryType.GetMethod("IncludeCount", bindingAttr, null, Type.EmptyTypes, null) ?? dataServiceQueryType.GetMethod("IncludeTotalCount", bindingAttr, null, Type.EmptyTypes, null);129			UnaryExpression body = Expression.Convert(Expression.Call(instanceExpression, method), typeof(object));130			return Expression.Lambda<Func<object, object>>(body, new ParameterExpression[1] { instanceParameter }).Compile();131		}132133		private static Func<object, long> BuildGetCountHandler(ParameterExpression instanceParameter, Type executeResultType)134		{135			PropertyInfo property = executeResultType.GetProperty("Count", BindingFlags.Instance | BindingFlags.Public) ?? executeResultType.GetProperty("TotalCount", BindingFlags.Instance | BindingFlags.Public);136			MemberExpression body = Expression.Property(Expression.Convert(instanceParameter, executeResultType), property);137			return Expression.Lambda<Func<object, long>>(body, new ParameterExpression[1] { instanceParameter }).Compile();138		}139140		private static Expression GetResultSynchronously(Expression taskExpression)141		{142			BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy;143			MethodInfo methodInfo = (from m in taskExpression.Type.GetMethods(bindingAttr)144				where m.Name == "GetAwaiter" && m.ReturnType.IsGenericType145				select m).Single();146			MethodInfo method = methodInfo.ReturnType.GetMethod("GetResult", bindingAttr, null, Type.EmptyTypes, null);147			return Expression.Call(Expression.Call(taskExpression, methodInfo), method);148		}149150		public IQueryable<T> AddQueryOption<T>(IQueryable<T> source, string name, object value)151		{152			return (IQueryable<T>)addQueryOptionHandler(source, name, value);153		}154155		public long GetCount(IQueryable dataServiceQuery)156		{157			IEnumerable arg = StaSafeHelper.Invoke(() => executeQueryHandler((IQueryable)includeCountHandler(dataServiceQuery)));158			return getCountHandler(arg);159		}160161		public IEnumerable<T> ExecuteWithContinuation<T>(IQueryable dataServiceQuery)162		{163			object token = null;164			object context = null;165			do166			{167				IEnumerable lastResult;168				if (token == null)169				{170					lastResult = StaSafeHelper.Invoke(() => executeQueryHandler(dataServiceQuery));171				}172				else173				{174					context = context ?? getContextHandler(dataServiceQuery);175					lastResult = StaSafeHelper.Invoke(() => executeContextHandler(context, token));176				}177				foreach (T item in lastResult)178				{179					yield return item;180				}181				token = getContinuationTokenHandler(lastResult);182			}183			while (token != null);184		}185	}186187	private class WrapperHelper188	{189		private readonly Type wrapperDataType;190191		private readonly Type elementType;192193		private readonly ConstructorInfo constructor;194195		private readonly ConstructorInfo constructorFromWrapper;196197		private readonly Func<object, object> createHandler;198199		private readonly Func<object, object> createFromWrapperHandler;200201		private readonly Dictionary<string, Func<object, object, object>> methodsDict = new Dictionary<string, Func<object, object, object>>();202203		private readonly Func<object, CriteriaOperator, bool, int, int, IQueryable> groupByHandler;204205		private readonly Dictionary<string, Func<object, object>> getPropertyDict = new Dictionary<string, Func<object, object>>();206207		public Type WrapperDataType => wrapperDataType;208209		public Type ElementType => elementType;210211		public WrapperHelper(Type wrapperDataType, Type elementType)212		{213			this.wrapperDataType = wrapperDataType;214			this.elementType = elementType;215			Type type = typeof(IQueryable<>).MakeGenericType(elementType);216			constructor = wrapperDataType.GetConstructor(new Type[7]217			{218				typeof(object),219				type,220				typeof(CriteriaOperator),221				typeof(int),222				typeof(int),223				typeof(int),224				typeof(string)225			});226			ParameterExpression parameterExpression = Expression.Parameter(typeof(object), "s");227			createHandler = Expression.Lambda<Func<object, object>>(Expression.New(constructor, Expression.Constant(null), Expression.Convert(parameterExpression, type), Expression.Constant(null, typeof(CriteriaOperator)), Expression.Constant(0), Expression.Constant(0), Expression.Constant(0), Expression.Constant(string.Empty)), new ParameterExpression[1] { parameterExpression }).Compile();228			constructorFromWrapper = wrapperDataType.GetConstructor(new Type[1] { wrapperDataType });229			createFromWrapperHandler = Expression.Lambda<Func<object, object>>(Expression.New(constructorFromWrapper, Expression.Convert(parameterExpression, wrapperDataType)), new ParameterExpression[1] { parameterExpression }).Compile();230			ParameterExpression parameterExpression2 = Expression.Parameter(typeof(object), "instance");231			ParameterExpression objParameter = Expression.Parameter(typeof(object), "obj");232			string[] array = new string[4] { "Max", "Min", "SelectFieldValues", "Where" };233			foreach (string text in array)234			{235				methodsDict.Add(text, CompileMethodCall(wrapperDataType, parameterExpression2, objParameter, text, typeof(CriteriaOperator)));236			}237			string[] array2 = new string[2] { "Skip", "Take" };238			foreach (string text2 in array2)239			{240				methodsDict.Add(text2, CompileMethodCall(wrapperDataType, parameterExpression2, objParameter, text2, typeof(int)));241			}242			methodsDict.Add("Select", CompileMethodCall(wrapperDataType, parameterExpression2, objParameter, "Select", typeof(string)));243			methodsDict.Add("SelectFieldValuesAndRows", CompileMethodCall(wrapperDataType, parameterExpression2, objParameter, "SelectFieldValuesAndRows", typeof(CriteriaOperator[])));244			methodsDict.Add("OrderBy", CompileMethodCall(wrapperDataType, parameterExpression2, objParameter, "OrderBy", typeof(ServerModeOrderDescriptor[])));245			MethodInfo method = wrapperDataType.GetMethod("GroupBy", new Type[4]246			{247				typeof(CriteriaOperator),248				typeof(bool),249				typeof(int),250				typeof(int)251			});252			ParameterExpression parameterExpression3 = Expression.Parameter(typeof(CriteriaOperator), "key");253			ParameterExpression parameterExpression4 = Expression.Parameter(typeof(bool), "isDesc");254			ParameterExpression parameterExpression5 = Expression.Parameter(typeof(int), "skip");255			ParameterExpression parameterExpression6 = Expression.Parameter(typeof(int), "top");256			groupByHandler = Expression.Lambda<Func<object, CriteriaOperator, bool, int, int, IQueryable>>(Expression.Call(Expression.Convert(parameterExpression2, wrapperDataType), method, parameterExpression3, parameterExpression4, parameterExpression5, parameterExpression6), new ParameterExpression[5] { parameterExpression2, parameterExpression3, parameterExpression4, parameterExpression5, parameterExpression6 }).Compile();257			string[] array3 = new string[2] { "Count", "Key" };258			foreach (string text3 in array3)259			{260				getPropertyDict.Add(text3, CompilePropertyGet(wrapperDataType, parameterExpression2, text3));261			}262		}263264		private Func<object, object, object> CompileMethodCall(Type wrapperDataType, ParameterExpression instanceParameter, ParameterExpression objParameter, string methodName, Type argumentType)265		{266			MethodInfo method = wrapperDataType.GetMethod(methodName, new Type[1] { argumentType });267			return Expression.Lambda<Func<object, object, object>>(Expression.Convert(Expression.Call(Expression.Convert(instanceParameter, wrapperDataType), method, Expression.Convert(objParameter, argumentType)), typeof(object)), new ParameterExpression[2] { instanceParameter, objParameter }).Compile();268		}269270		private Func<object, object> CompilePropertyGet(Type wrapperDataType, ParameterExpression instanceParameter, string propertyName)271		{272			PropertyInfo property = wrapperDataType.GetProperty(propertyName);273			MethodInfo getMethod = property.GetGetMethod();274			return Expression.Lambda<Func<object, object>>(Expression.Convert(Expression.Call(Expression.Convert(instanceParameter, wrapperDataType), getMethod), typeof(object)), new ParameterExpression[1] { instanceParameter }).Compile();275		}276277		public object Create(IQueryable source)278		{279			return createHandler(source);280		}281282		public object CreateFromWrapper(object wrapper)283		{284			return createFromWrapperHandler(wrapper);285		}286287		public object CallMethod(string methodName, object instance, object parameter)288		{289			if (!methodsDict.TryGetValue(methodName, out var value))290			{291				throw new MissingMethodException(instance.GetType().FullName, methodName);292			}293			return value(instance, parameter);294		}295296		public IQueryable GroupBy(object instance, CriteriaOperator key, bool isDesc, int skip, int top)297		{298			return groupByHandler(instance, key, isDesc, skip, top);299		}300301		public object GetPropertyValue(string propetyName, object instance)302		{303			if (!getPropertyDict.TryGetValue(propetyName, out var value))304			{305				throw new MissingMethodException(instance.GetType().FullName, propetyName);306			}307			return value(instance);308		}309	}310311	public abstract class ListHelperBase312	{313		public abstract void Add(object list, object obj);314315		public abstract void AddRange(object list, object range);316317		public abstract IQueryable AsQueryable(object list);318319		public abstract IQueryable Distinct(object list);320321		public abstract IQueryable OrderByKey(ICriteriaToExpressionConverter converter, object list, ServerModeOrderDescriptor descriptor);322323		public abstract object CreateNewList();324	}325326	public class ListHelper<T> : ListHelperBase327	{328		public override void Add(object list, object obj)329		{330			if (list is List<T> list2)331			{332				if (obj is T)333				{334					list2.Add((T)obj);335				}336				else if (obj == null)337				{338					list2.Add(default(T));339				}340			}341		}342343		public override void AddRange(object list, object range)344		{345			if (list is List<T> list2 && range is IEnumerable<T>)346			{347				list2.AddRange((IEnumerable<T>)range);348			}349		}350351		public override IQueryable AsQueryable(object list)352		{353			if (!(list is List<T> source))354			{355				return null;356			}357			return source.AsQueryable();358		}359360		public override IQueryable Distinct(object list)361		{362			if (!(list is List<T> source))363			{364				return null;365			}366			return source.Distinct().AsQueryable();367		}368369		public override object CreateNewList()370		{371			return new List<T>();372		}373374		private IQueryable CreateNewQueryable()375		{376			return new List<T>().AsQueryable();377		}378379		public override IQueryable OrderByKey(ICriteriaToExpressionConverter converter, object list, ServerModeOrderDescriptor descriptor)380		{381			if (!(list is List<T> source))382			{383				return null;384			}385			ParameterExpression parameterExpression = Expression.Parameter(typeof(T), "this");386			ParameterExpression expression = Expression.Parameter(typeof(Delegate), "predicate");387			Expression expression2 = converter.Convert(parameterExpression, descriptor.SortExpression);388			UnaryExpression unaryExpression = Expression.Convert(expression, typeof(Func<, >).MakeGenericType(typeof(T), expression2.Type));389			Delegate obj = Expression.Lambda(expression2, parameterExpression).Compile();390			if (descriptor.IsDesc)391			{392				return source.OrderByDescending((Func<T, object>)obj).AsQueryable();393			}394			return source.OrderBy((Func<T, object>)obj).AsQueryable();395		}396	}397398	private const string SkipMethodName = "Skip";399400	private const string TakeMethodName = "Take";401402	private const string WhereMethodName = "Where";403404	private const string OrderByMethodName = "OrderBy";405406	private const string SelectVRMethodName = "SelectFieldValuesAndRows";407408	private const string SelectVMethodName = "SelectFieldValues";409410	private const string GroupByMethodName = "GroupBy";411412	private const string MaxMethodName = "Max";413414	private const string MinMethodName = "Min";415416	private const string KeyPropertyName = "Key";417418	private const string CountPropertyName = "Count";419420	private const string SelectMethodName = "Select";421422	private static readonly ReaderWriterLockSlim wrapperDataTypeLock = new ReaderWriterLockSlim();423424	private static readonly Dictionary<Type, Type> wrapperDataTypeCache = new Dictionary<Type, Type>();425426	private static readonly Dictionary<Type, ListHelperBase> listHelperCache = new Dictionary<Type, ListHelperBase>();427428	private static readonly ReaderWriterLockSlim wrapperHelperLock = new ReaderWriterLockSlim();429430	private static readonly Dictionary<Type, WrapperHelper> wrapperHelperDict = new Dictionary<Type, WrapperHelper>();431432	private static readonly ReaderWriterLockSlim dataServiceQueryLock = new ReaderWriterLockSlim();433434	private static readonly Dictionary<Type, DataServiceQueryHelper> dataServiceQueryDict = new Dictionary<Type, DataServiceQueryHelper>();435436	private static readonly ElementDescriptorCache elementDescriptorCache = new ElementDescriptorCache();437438	public static readonly object NotSummarySupported = new object();439440	public static ElementDescriptor GetElementDescriptor(Type type)441	{442		return elementDescriptorCache.GetDescriptor(type);443	}444445	public static IEnumerable<T> ExecuteDataServiceQuery<T>(IQueryable source)446	{447		return GetDataServiceQueryHelper(source.GetType()).ExecuteWithContinuation<T>(source);448	}449450	public static long GetTotalCount<T>(IQueryable<T> source)451	{452		return GetDataServiceQueryHelper(source.GetType()).GetCount(source);453	}454455	public static IQueryable<T> AddQueryOption<T>(IQueryable<T> source, string name, object value)456	{457		return GetDataServiceQueryHelper(source.GetType()).AddQueryOption(source, name, value);458	}459460	private static DataServiceQueryHelper GetDataServiceQueryHelper(Type dataServiceQueryType)461	{462		DataServiceQueryHelper value = null;463		dataServiceQueryLock.EnterReadLock();464		try465		{466			dataServiceQueryDict.TryGetValue(dataServiceQueryType, out value);467		}468		finally469		{470			dataServiceQueryLock.ExitReadLock();471		}472		if (value == null)473		{474			dataServiceQueryLock.EnterWriteLock();475			try476			{477				dataServiceQueryDict.TryGetValue(dataServiceQueryType, out value);478				if (value == null)479				{480					value = new DataServiceQueryHelper(dataServiceQueryType);481					dataServiceQueryDict.Add(dataServiceQueryType, value);482				}483			}484			finally485			{486				dataServiceQueryLock.ExitWriteLock();487			}488		}489		return value;490	}491492	public static IQueryable GroupBy(this IQueryable source, CriteriaOperator groupCriteria, bool isDesc, int skip, int top)493	{494		Type wrapperDataType = GetWrapperDataType(source.ElementType);495		Type type = typeof(EnumerableQuery<>).MakeGenericType(wrapperDataType);496		ListHelperBase listHelper = GetListHelper(wrapperDataType);497		WrapperHelper wrapperHelper = GetWrapperHelper(wrapperDataType);498		object list = listHelper.CreateNewList();499		if (type.IsAssignableFrom(source.GetType()))500		{501			foreach (object item in source)502			{503				listHelper.Add(list, wrapperHelper.GroupBy(item, groupCriteria, isDesc, skip, top));504			}505			return listHelper.AsQueryable(list);506		}507		object instance = ((!wrapperDataType.IsAssignableFrom(source.GetType())) ? GetNewWrapperData(source, wrapperDataType) : source);508		return wrapperHelper.GroupBy(instance, groupCriteria, isDesc, skip, top);509	}510511	private static Type GetWrapperDataType(Type elementType)512	{513		wrapperDataTypeLock.EnterReadLock();514		Type value;515		try516		{517			if (wrapperDataTypeCache.TryGetValue(elementType, out value))518			{519				return value;520			}521		}522		finally523		{524			wrapperDataTypeLock.ExitReadLock();525		}526		value = ((!elementType.IsGenericType || !(elementType.GetGenericTypeDefinition() == typeof(WrapperDataServiceQuery<>))) ? typeof(WrapperDataServiceQuery<>).MakeGenericType(elementType) : elementType);527		wrapperDataTypeLock.EnterWriteLock();528		try529		{530			wrapperDataTypeCache[elementType] = value;531			return value;532		}533		finally534		{535			wrapperDataTypeLock.ExitWriteLock();536		}537	}538539	private static WrapperHelper GetWrapperHelper(Type wrapperDataType)540	{541		WrapperHelper value = null;542		wrapperHelperLock.EnterReadLock();543		try544		{545			wrapperHelperDict.TryGetValue(wrapperDataType, out value);546		}547		finally548		{549			wrapperHelperLock.ExitReadLock();550		}551		if (value == null)552		{553			wrapperHelperLock.EnterWriteLock();554			try555			{556				wrapperHelperDict.TryGetValue(wrapperDataType, out value);557				if (value == null)558				{559					value = new WrapperHelper(wrapperDataType, wrapperDataType.GetGenericArguments()[0]);560					wrapperHelperDict.Add(wrapperDataType, value);561				}562			}563			finally564			{565				wrapperHelperLock.ExitWriteLock();566			}567		}568		return value;569	}570571	private static object GetNewWrapperData(IQueryable source, Type wrapperDataType)572	{573		return GetWrapperHelper(wrapperDataType).Create(source);574	}575576	public static IEnumerable<object[]> SelectSummary(this IQueryable source, Type sourceType, ServerModeSummaryDescriptor[] summaries)577	{578		try579		{580			List<object[]> list = new List<object[]>();581			foreach (object item in source)582			{583				List<object> list2 = new List<object>();584				WrapperHelper wrapperHelper = GetWrapperHelper(GetWrapperDataType(sourceType));585				object instance = wrapperHelper.CreateFromWrapper(item);586				list2.Add(wrapperHelper.GetPropertyValue("Key", instance));587				list2.Add(wrapperHelper.GetPropertyValue("Count", instance));588				foreach (ServerModeSummaryDescriptor serverModeSummaryDescriptor in summaries)589				{590					switch (serverModeSummaryDescriptor.SummaryType)591					{592					case Aggregate.Count:593						list2.Add(wrapperHelper.GetPropertyValue("Count", instance));594						break;595					case Aggregate.Max:596						list2.Add(wrapperHelper.CallMethod("Max", instance, serverModeSummaryDescriptor.SummaryExpression));597						break;598					case Aggregate.Min:599						list2.Add(wrapperHelper.CallMethod("Min", instance, serverModeSummaryDescriptor.SummaryExpression));600						break;601					default:602						list2.Add(new SummaryNotSupported());603						break;604					}605				}606				list.Add(list2.ToArray());607			}608			return list;609		}610		catch611		{612			return null;613		}614	}615616	public static IQueryable SelectFieldValues(this IQueryable source, CriteriaOperator fieldCriteria)617	{618		return CallMethodWithParamOfTypeCriteriaOperator(source, fieldCriteria, "SelectFieldValues");619	}620621	public static WrapperResult SelectFieldValuesAndRows(this IQueryable source, CriteriaOperator[] fieldsCriteria)622	{623		return GetWrapperResult(source, fieldsCriteria, "SelectFieldValuesAndRows");624	}625626	public static IQueryable OrderBy(this IQueryable source, ServerModeOrderDescriptor[] order)627	{628		Type wrapperDataType = GetWrapperDataType(source.ElementType);629		Type type = typeof(EnumerableQuery<>).MakeGenericType(wrapperDataType);630		ListHelperBase listHelper = GetListHelper(wrapperDataType);631		WrapperHelper wrapperHelper = GetWrapperHelper(wrapperDataType);632		object list = listHelper.CreateNewList();633		if (type.IsAssignableFrom(source.GetType()))634		{635			foreach (object item in source)636			{637				listHelper.Add(list, (IQueryable)wrapperHelper.CallMethod("OrderBy", item, order));638			}639			ICriteriaToExpressionConverter converterForInstance = ODataServerModeCore.ConverterForInstance;640			foreach (ServerModeOrderDescriptor serverModeOrderDescriptor in order)641			{642				if (serverModeOrderDescriptor.SortExpression.Is((OperandProperty sortProperty) => sortProperty.PropertyName == "Key"))643				{644					return listHelper.OrderByKey(converterForInstance, list, serverModeOrderDescriptor);645				}646			}647			return listHelper.AsQueryable(list);648		}649		object instance = ((!wrapperDataType.IsAssignableFrom(source.GetType())) ? GetNewWrapperData(source, wrapperDataType) : source);650		return (IQueryable)wrapperHelper.CallMethod("OrderBy", instance, order);651	}652653	public static IQueryable Where(this IQueryable source, CriteriaOperator filterCriteria)654	{655		return CallMethodWithParamOfTypeCriteriaOperator(source, filterCriteria, "Where");656	}657658	public static IQueryable SkipData(this IQueryable source, int count)659	{660		return CallMethodWithParamOfTypeInt(source, count, "Skip");661	}662663	public static IQueryable TakeData(this IQueryable source, int count)664	{665		return CallMethodWithParamOfTypeInt(source, count, "Take");666	}667668	public static IQueryable SelectData(this IQueryable source, string selectExpression)669	{670		return CallMethodWithParamOfTypeString(source, selectExpression, "Select");671	}672673	private static IQueryable CallMethodWithParamOfTypeInt(IQueryable source, int count, string methodName)674	{675		Type wrapperDataType = GetWrapperDataType(source.ElementType);676		Type type = typeof(EnumerableQuery<>).MakeGenericType(wrapperDataType);677		ListHelperBase listHelper = GetListHelper(wrapperDataType);678		WrapperHelper wrapperHelper = GetWrapperHelper(wrapperDataType);679		object list = listHelper.CreateNewList();680		if (type.IsAssignableFrom(source.GetType()))681		{682			foreach (object item in source)683			{684				listHelper.Add(list, (IQueryable)wrapperHelper.CallMethod(methodName, item, count));685			}686			return listHelper.AsQueryable(list);687		}688		object instance = ((!wrapperDataType.IsAssignableFrom(source.GetType())) ? GetNewWrapperData(source, wrapperDataType) : source);689		return (IQueryable)wrapperHelper.CallMethod(methodName, instance, count);690	}691692	private static IQueryable CallMethodWithParamOfTypeString(IQueryable source, string str, string methodName)693	{694		Type wrapperDataType = GetWrapperDataType(source.ElementType);695		Type type = typeof(EnumerableQuery<>).MakeGenericType(wrapperDataType);696		ListHelperBase listHelper = GetListHelper(wrapperDataType);697		WrapperHelper wrapperHelper = GetWrapperHelper(wrapperDataType);698		object list = listHelper.CreateNewList();699		if (type.IsAssignableFrom(source.GetType()))700		{701			foreach (object item in source)702			{703				listHelper.Add(list, (IQueryable)wrapperHelper.CallMethod(methodName, item, str));704			}705			return listHelper.AsQueryable(list);706		}707		object instance = ((!wrapperDataType.IsAssignableFrom(source.GetType())) ? GetNewWrapperData(source, wrapperDataType) : source);708		return (IQueryable)wrapperHelper.CallMethod(methodName, instance, str);709	}710711	private static WrapperResult GetWrapperResult(IQueryable source, CriteriaOperator[] operands, string methodName)712	{713		Type wrapperDataType = GetWrapperDataType(source.ElementType);714		object instance = (wrapperDataType.IsAssignableFrom(source.GetType()) ? source : GetNewWrapperData(source, wrapperDataType));715		return (WrapperResult)GetWrapperHelper(wrapperDataType).CallMethod(methodName, instance, operands);716	}717718	private static IQueryable CallMethodWithParamOfTypeCriteriaOperator(IQueryable source, CriteriaOperator criteriaOp, string methodName)719	{720		Type wrapperDataType = GetWrapperDataType(source.ElementType);721		Type type = typeof(EnumerableQuery<>).MakeGenericType(wrapperDataType);722		WrapperHelper wrapperHelper = GetWrapperHelper(wrapperDataType);723		if (type.IsAssignableFrom(source.GetType()))724		{725			Type type2 = null;726			ListHelperBase listHelperBase = null;727			object list = null;728			foreach (object item in source)729			{730				IQueryable queryable = (IQueryable)wrapperHelper.CallMethod(methodName, item, criteriaOp);731				if (type2 == null && queryable != null)732				{733					type2 = queryable.ElementType;734					listHelperBase = GetListHelper(type2);735					list = listHelperBase.CreateNewList();736				}737				listHelperBase.AddRange(list, queryable);738			}739			if (listHelperBase != null)740			{741				return listHelperBase.AsQueryable(list);742			}743			return new List<object>().AsQueryable();744		}745		object instance = ((!wrapperDataType.IsAssignableFrom(source.GetType())) ? GetNewWrapperData(source, wrapperDataType) : source);746		return (IQueryable)wrapperHelper.CallMethod(methodName, instance, criteriaOp);747	}748749	private static ListHelperBase GetListHelper(Type wrapperDataType)750	{751		ListHelperBase value;752		lock (listHelperCache)753		{754			if (listHelperCache.TryGetValue(wrapperDataType, out value))755			{756				return value;757			}758		}759		Type type = typeof(ListHelper<>).MakeGenericType(wrapperDataType);760		value = (ListHelperBase)Activator.CreateInstance(type);761		lock (listHelperCache)762		{763			listHelperCache[wrapperDataType] = value;764			return value;765		}766	}767768	public static int CountOfData(IQueryable source)769	{770		return (int)GetWrapperHelper(GetWrapperDataType(source.ElementType)).GetPropertyValue("Count", source);771	}772}773