internal void Initialize(IWebApiAssembliesResolver assembliesResolver, bool isQueryCompositionMode) { _isQueryCompositionMode = isQueryCompositionMode; _configuredNavigationSources = new HashSet <NavigationSourceConfiguration>(); _mappedTypes = new HashSet <StructuralTypeConfiguration>(); _ignoredTypes = new HashSet <Type>(); ModelAliasingEnabled = true; _allTypesWithDerivedTypeMapping = new Lazy <IDictionary <Type, List <Type> > >( () => BuildDerivedTypesMapping(assembliesResolver), isThreadSafe: false); }
private Expression VerifyQueryDeserialization <T>(string clauseString, string expectedResult = null, Action <ODataQuerySettings> settingsCustomizer = null, bool classicEF = false) where T : class { IEdmModel model = GetModel <T>(); ApplyClause clause = CreateApplyNode(clauseString, model, typeof(T)); IWebApiAssembliesResolver assembliesResolver = WebApiAssembliesResolverFactory.Create(); Func <ODataQuerySettings, ODataQuerySettings> customizeSettings = (settings) => { if (settingsCustomizer != null) { settingsCustomizer.Invoke(settings); } return(settings); }; var context = new ODataQueryContext(model, typeof(T)) { RequestContainer = new MockContainer() }; var expandClause = clause.Transformations.OfType <ExpandTransformationNode>().FirstOrDefault()?.ExpandClause; var binder = classicEF ? new AggregationBinderEFFake( customizeSettings(new ODataQuerySettings { HandleNullPropagation = HandleNullPropagationOption.False }), assembliesResolver, typeof(T), model, clause.Transformations.First(t => t.Kind != TransformationNodeKind.Expand), context, expandClause) : new AggregationBinder( customizeSettings(new ODataQuerySettings { HandleNullPropagation = HandleNullPropagationOption.False }), assembliesResolver, typeof(T), model, clause.Transformations.First(t => t.Kind != TransformationNodeKind.Expand), context, expandClause); var query = Enumerable.Empty <T>().AsQueryable(); var queryResult = binder.Bind(query); var applyExpr = queryResult.Expression; VerifyExpression <T>(applyExpr, expectedResult); return(applyExpr); }
/// <summary> /// Initializes a new instance of the <see cref="ExpressionBinderBase"/> class. /// </summary> /// <param name="requestContainer">The request container.</param> protected ExpressionBinderBase(IServiceProvider requestContainer) { Contract.Assert(requestContainer != null); QuerySettings = requestContainer.GetRequiredService <ODataQuerySettings>(); Model = requestContainer.GetRequiredService <IEdmModel>(); // The IWebApiAssembliesResolver service is internal and can only be injected by WebApi. // This code path may be used in the cases when the service container available // but may not contain an instance of IWebApiAssembliesResolver. IWebApiAssembliesResolver injectedResolver = requestContainer.GetService <IWebApiAssembliesResolver>(); InternalAssembliesResolver = (injectedResolver != null) ? injectedResolver : WebApiAssembliesResolver.Default; }
private static Dictionary <Type, List <Type> > BuildDerivedTypesMapping(IWebApiAssembliesResolver assemblyResolver) { IEnumerable <Type> allTypes = TypeHelper.GetLoadedTypes(assemblyResolver).Where(t => TypeHelper.IsVisible(t) && TypeHelper.IsClass(t) && t != typeof(object)); Dictionary <Type, List <Type> > allTypeMapping = allTypes.Distinct().ToDictionary(k => k, k => new List <Type>()); foreach (Type type in allTypes) { List <Type> derivedTypes; if (TypeHelper.GetBaseType(type) != null && allTypeMapping.TryGetValue(TypeHelper.GetBaseType(type), out derivedTypes)) { derivedTypes.Add(type); } } return(allTypeMapping); }
internal AggregationBinder(ODataQuerySettings settings, IWebApiAssembliesResolver assembliesResolver, Type elementType, IEdmModel model, TransformationNode transformation) : base(model, assembliesResolver, settings) { Contract.Assert(elementType != null); Contract.Assert(transformation != null); _elementType = elementType; _transformation = transformation; this._lambdaParameter = Expression.Parameter(this._elementType, "$it"); switch (transformation.Kind) { case TransformationNodeKind.Aggregate: var aggregateClause = this._transformation as AggregateTransformationNode; _aggregateExpressions = FixCustomMethodReturnTypes(aggregateClause.AggregateExpressions); ResultClrType = typeof(NoGroupByAggregationWrapper); break; case TransformationNodeKind.GroupBy: var groupByClause = this._transformation as GroupByTransformationNode; _groupingProperties = groupByClause.GroupingProperties; if (groupByClause.ChildTransformations != null) { if (groupByClause.ChildTransformations.Kind == TransformationNodeKind.Aggregate) { var aggregationNode = (AggregateTransformationNode)groupByClause.ChildTransformations; _aggregateExpressions = FixCustomMethodReturnTypes(aggregationNode.AggregateExpressions); } else { throw new NotImplementedException(); } } _groupByClrType = typeof(GroupByWrapper); ResultClrType = typeof(AggregationWrapper); break; default: throw new NotSupportedException(String.Format(CultureInfo.InvariantCulture, SRResources.NotSupportedTransformationKind, transformation.Kind)); } _groupByClrType = _groupByClrType ?? typeof(NoGroupByWrapper); }
private static Dictionary <Type, Type[]> BuildDerivedTypesMapping(IWebApiAssembliesResolver assemblyResolver) { Predicate <Type> verifyType = t => TypeHelper.IsVisible(t) && TypeHelper.IsClass(t) && t != typeof(object); // The dictionary is allocated to contain all visible reference types which is not system.Object, each with an List<Type> allocated. // The list is used to keep derived types. // In a common scenario, there are about 10% types with derived types. // So, we don't need to keep a large number of empty list in the dictionary. Dictionary <Type, List <Type> > temp = new Dictionary <Type, List <Type> >(); foreach (Type type in TypeHelper.GetLoadedTypes(assemblyResolver)) { if (type != null && verifyType(type)) { Type baseType = TypeHelper.GetBaseType(type); if (baseType != null) { List <Type> list; if (!temp.TryGetValue(baseType, out list)) { if (verifyType(baseType)) { list = new List <Type>(1); temp[baseType] = list; } } if (list != null) { list.Add(type); } } } } // We can throw away all lists and keep the dictionary as small as possible Dictionary <Type, Type[]> map = new Dictionary <Type, Type[]>(temp.Count); foreach (var kv in temp) { map[kv.Key] = kv.Value.ToArray(); } return(map); }
// This code is copied from DefaultHttpControllerTypeResolver.GetControllerTypes. internal static IEnumerable <Type> GetLoadedTypes(IWebApiAssembliesResolver assembliesResolver) { List <Type> result = new List <Type>(); if (assembliesResolver == null) { return(result); } // Go through all assemblies referenced by the application and search for types matching a predicate IEnumerable <Assembly> assemblies = assembliesResolver.Assemblies; foreach (Assembly assembly in assemblies) { Type[] exportedTypes = null; if (assembly == null || assembly.IsDynamic) { // can't call GetTypes on a null (or dynamic?) assembly continue; } try { exportedTypes = assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { exportedTypes = ex.Types; } catch { continue; } if (exportedTypes != null) { result.AddRange(exportedTypes.Where(t => t != null && TypeHelper.IsVisible(t))); } } return(result); }
// This code is copied from DefaultHttpControllerTypeResolver.GetControllerTypes. internal static IEnumerable <Type> GetLoadedTypes(IWebApiAssembliesResolver assembliesResolver) { if (assembliesResolver != null) { // Go through all assemblies referenced by the application and search for types matching a predicate IEnumerable <Assembly> assemblies = assembliesResolver.Assemblies; foreach (Assembly assembly in assemblies) { Type[] exportedTypes = null; if (assembly == null || assembly.IsDynamic) { // can't call GetTypes on a null (or dynamic?) assembly continue; } try { exportedTypes = assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { exportedTypes = ex.Types; } catch { continue; } if (exportedTypes != null) { foreach (Type t in exportedTypes) { if ((t != null) && (TypeHelper.IsVisible(t))) { yield return(t); } } } } } }
internal static Expression Bind(FilterClause filterClause, Type filterType, IEdmModel model, IWebApiAssembliesResolver assembliesResolver, ODataQuerySettings querySettings) { if (filterClause == null) { throw Error.ArgumentNull("filterClause"); } if (filterType == null) { throw Error.ArgumentNull("filterType"); } if (model == null) { throw Error.ArgumentNull("model"); } if (assembliesResolver == null) { throw Error.ArgumentNull("assembliesResolver"); } FilterBinder binder = new FilterBinder(model, assembliesResolver, querySettings, filterType); return(BindFilterClause(binder, filterClause, filterType)); }
/// <summary> /// Apply the apply query to the given IQueryable. /// </summary> /// <remarks> /// The <see cref="ODataQuerySettings.HandleNullPropagation"/> property specifies /// how this method should handle null propagation. /// </remarks> /// <param name="query">The original <see cref="IQueryable"/>.</param> /// <param name="querySettings">The <see cref="ODataQuerySettings"/> that contains all the query application related settings.</param> /// <returns>The new <see cref="IQueryable"/> after the filter query has been applied to.</returns> public IQueryable ApplyTo(IQueryable query, ODataQuerySettings querySettings) { if (query == null) { throw Error.ArgumentNull("query"); } if (querySettings == null) { throw Error.ArgumentNull("querySettings"); } if (Context.ElementClrType == null) { throw Error.NotSupported(SRResources.ApplyToOnUntypedQueryOption, "ApplyTo"); } // Linq to SQL not supported for $apply if (query.Provider.GetType().Namespace == HandleNullPropagationOptionHelper.Linq2SqlQueryProviderNamespace) { throw Error.NotSupported(SRResources.ApplyQueryOptionNotSupportedForLinq2SQL); } ApplyClause applyClause = ApplyClause; Contract.Assert(applyClause != null); ODataQuerySettings updatedSettings = Context.UpdateQuerySettings(querySettings, query); // The IWebApiAssembliesResolver service is internal and can only be injected by WebApi. // This code path may be used in cases when the service container is not available // and the service container is available but may not contain an instance of IWebApiAssembliesResolver. IWebApiAssembliesResolver assembliesResolver = WebApiAssembliesResolver.Default; if (Context.RequestContainer != null) { IWebApiAssembliesResolver injectedResolver = Context.RequestContainer.GetService <IWebApiAssembliesResolver>(); if (injectedResolver != null) { assembliesResolver = injectedResolver; } } foreach (var transformation in applyClause.Transformations) { if (transformation.Kind == TransformationNodeKind.Aggregate || transformation.Kind == TransformationNodeKind.GroupBy) { var binder = new AggregationBinder(updatedSettings, assembliesResolver, ResultClrType, Context.Model, transformation); query = binder.Bind(query); this.ResultClrType = binder.ResultClrType; } else if (transformation.Kind == TransformationNodeKind.Filter) { var filterTransformation = transformation as FilterTransformationNode; Expression filter = FilterBinder.Bind(query, filterTransformation.FilterClause, ResultClrType, Context, querySettings); query = ExpressionHelpers.Where(query, filter, ResultClrType); } } return(query); }
internal ExpressionBinderBase(IEdmModel model, IWebApiAssembliesResolver assembliesResolver, ODataQuerySettings querySettings) : this(model, querySettings) { InternalAssembliesResolver = assembliesResolver; }
internal AggregationBinderEFFake(ODataQuerySettings settings, IWebApiAssembliesResolver assembliesResolver, Type elementType, IEdmModel model, TransformationNode transformation) : base(settings, assembliesResolver, elementType, model, transformation) { }
private static IEnumerable <Type> GetMatchingTypes(string edmFullName, IWebApiAssembliesResolver assembliesResolver) { return(TypeHelper.GetLoadedTypes(assembliesResolver).Where(t => TypeHelper.IsPublic(t) && t.EdmFullName() == edmFullName)); }
internal AggregationBinderEFFake(ODataQuerySettings settings, IWebApiAssembliesResolver assembliesResolver, Type elementType, IEdmModel model, TransformationNode transformation, ODataQueryContext context, SelectExpandClause selectExpandClause = null) : base(settings, assembliesResolver, elementType, model, transformation, context, selectExpandClause) { }
public static Type GetClrType(IEdmTypeReference edmTypeReference, IEdmModel edmModel, IWebApiAssembliesResolver assembliesResolver) { if (edmTypeReference == null) { throw Error.ArgumentNull("edmTypeReference"); } Type primitiveClrType = _builtInTypesMapping .Where(kvp => edmTypeReference.Definition.IsEquivalentTo(kvp.Value) && (!edmTypeReference.IsNullable || IsNullable(kvp.Key))) .Select(kvp => kvp.Key) .FirstOrDefault(); if (primitiveClrType != null) { return(primitiveClrType); } else { Type clrType = GetClrType(edmTypeReference.Definition, edmModel, assembliesResolver); if (clrType != null && TypeHelper.IsEnum(clrType) && edmTypeReference.IsNullable) { return(TypeHelper.ToNullable(clrType)); } return(clrType); } }
internal ComputeBinder(ODataQuerySettings settings, IWebApiAssembliesResolver assembliesResolver, Type elementType, IEdmModel model, ComputeTransformationNode transformation) : this(settings, assembliesResolver, elementType, model, transformation.Expressions) { }
internal static Expression <Func <TEntityType, bool> > Bind <TEntityType>(FilterClause filterClause, IEdmModel model, IWebApiAssembliesResolver assembliesResolver, ODataQuerySettings querySettings) { return(Bind(filterClause, typeof(TEntityType), model, assembliesResolver, querySettings) as Expression <Func <TEntityType, bool> >); }
internal FilterBinder(ODataQuerySettings settings, IWebApiAssembliesResolver assembliesResolver, IEdmModel model) : base(model, assembliesResolver, settings) { }
/// <summary> /// Initializes a new <see cref="ODataConventionModelBuilder"/>. /// </summary> /// <param name="resolver">The <see cref="IWebApiAssembliesResolver"/> to use.</param> internal ODataConventionModelBuilder(IWebApiAssembliesResolver resolver) : this(resolver, isQueryCompositionMode : false) { }
internal TransformationBinderBase(ODataQuerySettings settings, IWebApiAssembliesResolver assembliesResolver, Type elementType, IEdmModel model) : base(model, assembliesResolver, settings) { Contract.Assert(elementType != null); LambdaParameter = Expression.Parameter(elementType, "$it"); }