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);
 }
Beispiel #2
0
        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;
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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);
        }
Beispiel #7
0
        // 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);
        }
Beispiel #8
0
        // 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);
                            }
                        }
                    }
                }
            }
        }
Beispiel #9
0
        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));
        }
Beispiel #10
0
        /// <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;
 }
Beispiel #12
0
 internal AggregationBinderEFFake(ODataQuerySettings settings, IWebApiAssembliesResolver assembliesResolver, Type elementType, IEdmModel model, TransformationNode transformation)
     : base(settings, assembliesResolver, elementType, model, transformation)
 {
 }
Beispiel #13
0
 private static IEnumerable <Type> GetMatchingTypes(string edmFullName, IWebApiAssembliesResolver assembliesResolver)
 {
     return(TypeHelper.GetLoadedTypes(assembliesResolver).Where(t => TypeHelper.IsPublic(t) && t.EdmFullName() == edmFullName));
 }
Beispiel #14
0
 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)
 {
 }
Beispiel #15
0
        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);
            }
        }
Beispiel #16
0
 internal ComputeBinder(ODataQuerySettings settings, IWebApiAssembliesResolver assembliesResolver, Type elementType,
                        IEdmModel model, ComputeTransformationNode transformation)
     : this(settings, assembliesResolver, elementType, model, transformation.Expressions)
 {
 }
Beispiel #17
0
 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> >);
 }
Beispiel #18
0
 internal FilterBinder(ODataQuerySettings settings, IWebApiAssembliesResolver assembliesResolver, IEdmModel model)
     : base(model, assembliesResolver, settings)
 {
 }
Beispiel #19
0
 /// <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");
 }