DevExpress.Data.v24.2/DevExpress.Data.ODataLinq.Helpers/ODataLinqHelpers.cs
Decompiler Source FileDevExpress.Data.v24.2.ODataLinqHelpersDecompiled Source
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
Classes
ODataLinqHelpers DataServiceQueryHelper WrapperHelper ListHelperBase ListHelperMethods
- FitToSignature
- GetResultSynchronously
- GetCount
- Create
- CreateFromWrapper
- CallMethod
- GroupBy
- GetPropertyValue
- Add
- AddRange
- AsQueryable
- Distinct
- OrderByKey
- CreateNewList
- CreateNewQueryable
- GetElementDescriptor
- GetDataServiceQueryHelper
- GetWrapperDataType
- GetWrapperHelper
- GetNewWrapperData
- SelectSummary
- SelectFieldValues
- SelectFieldValuesAndRows
- OrderBy
- Where
- SkipData
- TakeData
- SelectData
- CallMethodWithParamOfTypeInt
- CallMethodWithParamOfTypeString
- GetWrapperResult
- CallMethodWithParamOfTypeCriteriaOperator
- GetListHelper
- CountOfData
DB/Dialog object references
None extracted.
OIM key/entity markers
None extracted.API/entity calls
None extracted.Registrations / handlers
None extracted.
Complete Source
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