/// <summary> /// Creates a new instance. /// </summary> internal static IMapper <TOptions, TValue> Create(Expression <Func <TOptions, TValue> > expression) { var action = ExpressionHelpers.CreatePropertyWriter(expression, out var propertyName); return(new PropertyMapper <TOptions, TValue>(action, propertyName)); }
protected override Expression VisitMethodCall(MethodCallExpression node) { if (!IsParentParameterExpression()) { return(base.VisitMethodCall(node)); } if (!object.ReferenceEquals(CurrentParameter, node.GetParameterExpression())) { return(base.VisitMethodCall(node)); } if (node.Method.IsStatic) { if (!IsExtentionMethod()) { return(base.VisitMethodCall(node)); } if (node.Method.IsGenericMethod) { return(Expression.Call ( node.Method.DeclaringType, node.Method.Name, node.Method.GetGenericArguments(), GetNewArgumentsForExtensionMethod() )); } else { return(Expression.Call(node.Method, GetNewArgumentsForExtensionMethod())); } } //instance method if (node.Method.IsGenericMethod) { return(Expression.Call ( GetNewParent(), node.Method.Name, node.Method.GetGenericArguments(), node.Arguments.ToArray() )); } else { return(Expression.Call ( GetNewParent(), node.Method, node.Arguments )); } Expression[] GetNewArgumentsForExtensionMethod() { Expression[] arguments = node.Arguments.ToArray(); arguments[0] = GetNewParent(); return(arguments.ToArray()); } Expression GetNewParent() => string.IsNullOrEmpty(ParentFullName) ? NewParameter : ExpressionHelpers.MemberAccesses(ParentFullName, NewParameter); bool IsParentParameterExpression() { if (node.Method.IsStatic) { return(node.Arguments[0] is ParameterExpression); } if (!node.Method.IsStatic) { return(node.Object is ParameterExpression); } return(false); } bool IsExtentionMethod() => node.Method.IsDefined(typeof(ExtensionAttribute), true); }
private IQueryable ApplyToCore(IQueryable query) { return(ExpressionHelpers.Skip(query, Value, Context.EntityClrType)); }
private IOrderedQueryable ApplyToCore(IQueryable query, ODataQuerySettings querySettings) { if (Context.ElementClrType == null) { throw Error.NotSupported(SRResources.ApplyToOnUntypedQueryOption, "ApplyTo"); } ICollection <OrderByNode> nodes = OrderByNodes; bool alreadyOrdered = false; IQueryable querySoFar = query; HashSet <object> propertiesSoFar = new HashSet <object>(); HashSet <string> openPropertiesSoFar = new HashSet <string>(); bool orderByItSeen = false; foreach (OrderByNode node in nodes) { OrderByPropertyNode propertyNode = node as OrderByPropertyNode; OrderByOpenPropertyNode openPropertyNode = node as OrderByOpenPropertyNode; OrderByCountNode countNode = node as OrderByCountNode; if (propertyNode != null) { // Use autonomy class to achieve value equality for HasSet. var edmPropertyWithPath = new { propertyNode.Property, propertyNode.PropertyPath }; OrderByDirection direction = propertyNode.Direction; // This check prevents queries with duplicate properties (e.g. $orderby=Id,Id,Id,Id...) from causing stack overflows if (propertiesSoFar.Contains(edmPropertyWithPath)) { throw new ODataException(Error.Format(SRResources.OrderByDuplicateProperty, edmPropertyWithPath.PropertyPath)); } propertiesSoFar.Add(edmPropertyWithPath); if (propertyNode.OrderByClause != null) { querySoFar = AddOrderByQueryForProperty(query, querySettings, propertyNode.OrderByClause, querySoFar, direction, alreadyOrdered); } else { querySoFar = ExpressionHelpers.OrderByProperty(querySoFar, Context.Model, edmPropertyWithPath.Property, direction, Context.ElementClrType, alreadyOrdered); } alreadyOrdered = true; } else if (openPropertyNode != null) { // This check prevents queries with duplicate properties (e.g. $orderby=Id,Id,Id,Id...) from causing stack overflows if (openPropertiesSoFar.Contains(openPropertyNode.PropertyName)) { throw new ODataException(Error.Format(SRResources.OrderByDuplicateProperty, openPropertyNode.PropertyPath)); } openPropertiesSoFar.Add(openPropertyNode.PropertyName); Contract.Assert(openPropertyNode.OrderByClause != null); querySoFar = AddOrderByQueryForProperty(query, querySettings, openPropertyNode.OrderByClause, querySoFar, openPropertyNode.Direction, alreadyOrdered); alreadyOrdered = true; } else if (countNode != null) { Contract.Assert(countNode.OrderByClause != null); querySoFar = AddOrderByQueryForProperty(query, querySettings, countNode.OrderByClause, querySoFar, countNode.Direction, alreadyOrdered); alreadyOrdered = true; } else { // This check prevents queries with duplicate nodes (e.g. $orderby=$it,$it,$it,$it...) from causing stack overflows if (orderByItSeen) { throw new ODataException(Error.Format(SRResources.OrderByDuplicateIt)); } querySoFar = ExpressionHelpers.OrderByIt(querySoFar, node.Direction, Context.ElementClrType, alreadyOrdered); alreadyOrdered = true; orderByItSeen = true; } } return(querySoFar as IOrderedQueryable); }
private Expression BuildPropertyContainer(IEdmEntityType elementType, Expression source, Dictionary <IEdmNavigationProperty, ExpandedNavigationSelectItem> propertiesToExpand, ISet <IEdmStructuralProperty> propertiesToInclude, ISet <IEdmStructuralProperty> autoSelectedProperties, bool isSelectingOpenTypeSegments) { IList <NamedPropertyExpression> includedProperties = new List <NamedPropertyExpression>(); foreach (KeyValuePair <IEdmNavigationProperty, ExpandedNavigationSelectItem> kvp in propertiesToExpand) { IEdmNavigationProperty propertyToExpand = kvp.Key; ExpandedNavigationSelectItem expandItem = kvp.Value; SelectExpandClause projection = expandItem.SelectAndExpand; Expression propertyName = CreatePropertyNameExpression(elementType, propertyToExpand, source); Expression propertyValue = CreatePropertyValueExpressionWithFilter(elementType, propertyToExpand, source, expandItem.FilterOption); Expression nullCheck = GetNullCheckExpression(propertyToExpand, propertyValue, projection); Expression countExpression = CreateTotalCountExpression(propertyValue, expandItem); // projection can be null if the expanded navigation property is not further projected or expanded. if (projection != null) { propertyValue = ProjectAsWrapper(propertyValue, projection, propertyToExpand.ToEntityType(), expandItem.NavigationSource as IEdmEntitySet, expandItem); } NamedPropertyExpression propertyExpression = new NamedPropertyExpression(propertyName, propertyValue); if (projection != null) { if (!propertyToExpand.Type.IsCollection()) { propertyExpression.NullCheck = nullCheck; } else if (_settings.PageSize != null) { propertyExpression.PageSize = _settings.PageSize.Value; } propertyExpression.TotalCount = countExpression; propertyExpression.CountOption = expandItem.CountOption; } includedProperties.Add(propertyExpression); } foreach (IEdmStructuralProperty propertyToInclude in propertiesToInclude) { Expression propertyName = CreatePropertyNameExpression(elementType, propertyToInclude, source); Expression propertyValue = CreatePropertyValueExpression(elementType, propertyToInclude, source); includedProperties.Add(new NamedPropertyExpression(propertyName, propertyValue)); } foreach (IEdmStructuralProperty propertyToInclude in autoSelectedProperties) { Expression propertyName = CreatePropertyNameExpression(elementType, propertyToInclude, source); Expression propertyValue = CreatePropertyValueExpression(elementType, propertyToInclude, source); includedProperties.Add(new NamedPropertyExpression(propertyName, propertyValue) { AutoSelected = true }); } if (isSelectingOpenTypeSegments) { var dynamicPropertyDictionary = EdmLibHelpers.GetDynamicPropertyDictionary(elementType, _model); Expression propertyName = Expression.Constant(dynamicPropertyDictionary.Name); Expression propertyValue = Expression.Property(source, dynamicPropertyDictionary.Name); Expression nullablePropertyValue = ExpressionHelpers.ToNullable(propertyValue); if (_settings.HandleNullPropagation == HandleNullPropagationOption.True) { // source == null ? null : propertyValue propertyValue = Expression.Condition( test: Expression.Equal(source, Expression.Constant(value: null)), ifTrue: Expression.Constant(value: null, type: propertyValue.Type.ToNullable()), ifFalse: nullablePropertyValue); } else { propertyValue = nullablePropertyValue; } includedProperties.Add(new NamedPropertyExpression(propertyName, propertyValue)); } // create a property container that holds all these property names and values. return(PropertyContainer.CreatePropertyContainer(includedProperties)); }
public static IHtmlContent GenerateHtml <TModel, TProperty>(IHtmlHelper <TModel> htmlHelper, Expression <Func <TModel, TProperty> > propertyLambdaExpression, FieldsetViewModel fieldsetOptions = null, HintViewModel hintOptions = null, Dictionary <TProperty, LabelViewModel> itemLabelOptions = null, Dictionary <TProperty, HintViewModel> itemHintOptions = null, Dictionary <TProperty, Func <object, object> > conditionalOptions = null, string classes = null) where TModel : GovUkViewModel { PropertyInfo property = ExpressionHelpers.GetPropertyFromExpression(propertyLambdaExpression); ThrowIfPropertyTypeIsNotNullableEnum(property); string propertyName = property.Name; TModel model = htmlHelper.ViewData.Model; TProperty currentlySelectedValue = ExpressionHelpers.GetPropertyValueFromModelAndExpression(model, propertyLambdaExpression); Type enumType = Nullable.GetUnderlyingType(typeof(TProperty)); Array allEnumValues = Enum.GetValues(enumType); List <ItemViewModel> radios = allEnumValues .OfType <object>() .Select(enumValue => { bool isEnumValueCurrentlySelected = enumValue.ToString() == currentlySelectedValue.ToString(); string radioLabelText = GetRadioLabelText(enumType, enumValue); var radioItemViewModel = new RadioItemViewModel { Value = enumValue.ToString(), Id = $"GovUk_Radio_{propertyName}_{enumValue}", Checked = isEnumValueCurrentlySelected, Label = new LabelViewModel() }; if (conditionalOptions != null && conditionalOptions.TryGetValue((TProperty)enumValue, out Func <object, object> conditionalHtml)) { radioItemViewModel.Conditional = new Conditional { Html = conditionalHtml }; } if (itemLabelOptions != null && itemLabelOptions.TryGetValue((TProperty)enumValue, out LabelViewModel labelViewModel)) { radioItemViewModel.Label = labelViewModel; } if (radioItemViewModel.Label.Text == null && radioItemViewModel.Label.Html == null) { radioItemViewModel.Label.Text = radioLabelText; } if (itemHintOptions != null && itemHintOptions.TryGetValue((TProperty)enumValue, out HintViewModel hintViewModel)) { radioItemViewModel.Hint = hintViewModel; } return(radioItemViewModel); }) .Cast <ItemViewModel>() .ToList(); var radiosViewModel = new RadiosViewModel { Name = $"GovUk_Radio_{propertyName}", IdPrefix = $"GovUk_{propertyName}", Items = radios, Fieldset = fieldsetOptions, Hint = hintOptions, Classes = classes }; if (model.HasErrorFor(property)) { radiosViewModel.ErrorMessage = new ErrorMessageViewModel { Text = model.GetErrorFor(property) }; } return(htmlHelper.Partial("/GovUkDesignSystemComponents/Radios.cshtml", radiosViewModel)); }
public void ExpressionChecker_NoException(int memberValue) { Assert.DoesNotThrow(() => ExpressionHelpers <Tick> .CheckMemberExpression(x => x.Volume, memberValue)); }
protected override Expression VisitMember(MemberExpression node) { string sourcePath; var parameterExpression = node.GetParameterExpression(); if (parameterExpression == null) { return(base.VisitMember(node)); } InfoDictionary.Add(parameterExpression, TypeMappings); var sType = parameterExpression.Type; if (InfoDictionary.ContainsKey(parameterExpression) && node.IsMemberExpression()) { sourcePath = node.GetPropertyFullName(); } else { return(base.VisitMember(node)); } var propertyMapInfoList = new List <PropertyMapInfo>(); FindDestinationFullName(sType, InfoDictionary[parameterExpression].DestType, sourcePath, propertyMapInfoList); string fullName; if (propertyMapInfoList.Any(x => x.CustomExpression != null)) { var last = propertyMapInfoList.Last(x => x.CustomExpression != null); var beforeCustExpression = propertyMapInfoList.Aggregate(new List <PropertyMapInfo>(), (list, next) => { if (propertyMapInfoList.IndexOf(next) < propertyMapInfoList.IndexOf(last)) { list.Add(next); } return(list); }); var afterCustExpression = propertyMapInfoList.Aggregate(new List <PropertyMapInfo>(), (list, next) => { if (propertyMapInfoList.IndexOf(next) > propertyMapInfoList.IndexOf(last)) { list.Add(next); } return(list); }); fullName = BuildFullName(beforeCustExpression); var visitor = new PrependParentNameVisitor(last.CustomExpression.Parameters[0].Type /*Parent type of current property*/, fullName, InfoDictionary[parameterExpression].NewParameter); var ex = propertyMapInfoList[propertyMapInfoList.Count - 1] != last ? visitor.Visit(last.CustomExpression.Body.MemberAccesses(afterCustExpression)) : visitor.Visit(last.CustomExpression.Body); this.TypeMappings.AddTypeMapping(ConfigurationProvider, node.Type, ex.Type); return(ex); } fullName = BuildFullName(propertyMapInfoList); var me = ExpressionHelpers.MemberAccesses(fullName, InfoDictionary[parameterExpression].NewParameter); this.TypeMappings.AddTypeMapping(ConfigurationProvider, node.Type, me.Type); return(me); }
private IOrderedQueryable ApplyToCore(IQueryable query, ODataQuerySettings querySettings) { if (Context.ElementClrType == null) { throw Error.NotSupported(SRResources.ApplyToOnUntypedQueryOption, "ApplyTo"); } ICollection <OrderByNode> nodes = OrderByNodes; bool alreadyOrdered = false; IQueryable querySoFar = query; HashSet <IEdmProperty> propertiesSoFar = new HashSet <IEdmProperty>(); bool orderByItSeen = false; foreach (OrderByNode node in nodes) { OrderByPropertyNode propertyNode = node as OrderByPropertyNode; if (propertyNode != null) { IEdmProperty property = propertyNode.Property; OrderByDirection direction = propertyNode.Direction; // This check prevents queries with duplicate properties (e.g. $orderby=Id,Id,Id,Id...) from causing stack overflows if (propertiesSoFar.Contains(property)) { throw new ODataException(Error.Format(SRResources.OrderByDuplicateProperty, property.Name)); } propertiesSoFar.Add(property); if (propertyNode.OrderByClause != null) { // Ensure we have decided how to handle null propagation ODataQuerySettings updatedSettings = querySettings; if (querySettings.HandleNullPropagation == HandleNullPropagationOption.Default) { updatedSettings = new ODataQuerySettings(updatedSettings); updatedSettings.HandleNullPropagation = HandleNullPropagationOptionHelper.GetDefaultHandleNullPropagationOption(query); } LambdaExpression orderByExpression = FilterBinder.Bind(propertyNode.OrderByClause, Context.ElementClrType, Context.Model, updatedSettings); querySoFar = ExpressionHelpers.OrderBy(querySoFar, orderByExpression, direction, Context.ElementClrType, alreadyOrdered); } else { querySoFar = ExpressionHelpers.OrderByProperty(querySoFar, Context.Model, property, direction, Context.ElementClrType, alreadyOrdered); } alreadyOrdered = true; } else { // This check prevents queries with duplicate nodes (e.g. $orderby=$it,$it,$it,$it...) from causing stack overflows if (orderByItSeen) { throw new ODataException(Error.Format(SRResources.OrderByDuplicateIt)); } querySoFar = ExpressionHelpers.OrderByIt(querySoFar, node.Direction, Context.ElementClrType, alreadyOrdered); alreadyOrdered = true; orderByItSeen = true; } } return(querySoFar as IOrderedQueryable); }
public void ExpressionChecker_NoException(string memberValue) { Assert.DoesNotThrow(() => ExpressionHelpers <Tick> .CheckMemberExpression(x => x.Symbol, memberValue)); }
public static IIndex <TDatabase, TTable> Index <TDatabase, TTable>(this IIndexBuilder <TDatabase, TTable> @this, Expression <Func <IOrderFilter <TTable>, object> > keyColumns, bool unique = false, string name = null, bool clustered = false, Expression <Func <TTable, object> > includedColumns = null) { var builder = @this as InternalTableBuilder <TDatabase, TTable>; var indexKeyColumns = ExpressionHelpers.ParseOrderedMultiPropertySelector(keyColumns ?? throw ModelBuilderError.ArgumentNull(nameof(keyColumns)).AsException()).MatchColumns(builder.Name, builder.Columns); var indexIncludedColumns = includedColumns == null?ImmutableArray.Create <ColumnModel>() : ExpressionHelpers.ParseMultiPropertySelector(includedColumns).MatchColumns(builder.Name, builder.Columns); var indexName = name ?? BuilderHelper.GenerateKeyName("IX", builder.Schema, builder.Name, indexKeyColumns.Select(c => c.Name)); if (clustered) { var priorClustered = builder.PrimaryKey?.IsClustered == true ? builder.PrimaryKey.Name : builder.Indexes.FirstOrDefault(i => i.IsClustered)?.Name; if (priorClustered != null) { throw ModelBuilderError.IndexClusteredAlreadySpecified(priorClustered).AsException(); } } { var column = indexIncludedColumns.FirstOrDefault(i => indexKeyColumns.Any(k => k.Property.Name == i.Property.Name)); if (column != null) { throw ModelBuilderError.IndexIncludedColumnAlreadyInKeyColumns(column.Name).AsException(); } } builder.Indexes.Add(new IndexModel(name: indexName, keyColumns: indexKeyColumns.ToImmutableArray(), isUnique: unique, isClustered: clustered, includedColumns: indexIncludedColumns.ToImmutableArray())); return(builder); }
public static Task <JobMetadataResult[]> SearchCriteria(JobSearchCriteria criteria) { var manager = new SQLiteJobQueueManager(new SQLiteJobQueueDataConnectionFactory(TempDevInfo.ConnString), TempDevInfo.TableConfigurations["console"], new NullOnMissingTypeJobTypeResolver()); Expression <Func <SqlCommonDbOddJobMetaData, bool> > expr = null; if (!string.IsNullOrWhiteSpace(criteria.QueueName)) { expr = ExpressionHelpers.CombineBinaryExpression(expr, (a) => a.QueueName.ToLower().Contains(criteria.QueueName.ToLower()), false); } if (!string.IsNullOrWhiteSpace(criteria.MethodName) && criteria.UseMethod) { expr = ExpressionHelpers.CombineBinaryExpression(expr, (a) => a.MethodName.ToLower().Contains(criteria.MethodName.ToLower()), false); } if (!string.IsNullOrWhiteSpace(criteria.Status) && criteria.UseStatus) { expr = ExpressionHelpers.CombineBinaryExpression(expr, (a) => a.Status.ToLower().Contains(criteria.Status.ToLower()), false); } /* if (statusCriteria != null && statusCriteria.Any()) * { * expr = ExpressionHelpers.CombineBinaryExpression(expr, (a) => a.Status.LikeAnyLower(statusCriteria), * requireAll); * * } * * if (jobNameCriteria != null && jobNameCriteria.Any()) * { * expr = ExpressionHelpers.CombineBinaryExpression(expr, * (a) => a.MethodName.LikeAnyUpper(jobNameCriteria), requireAll); * } * * if (jobGuids != null && jobGuids.Any()) * { * expr = ExpressionHelpers.CombineBinaryExpression(expr, (a) => a.JobGuid.In(jobGuids), requireAll); * } * * expr = ExpressionHelpers.CombineBinaryExpression(expr, (a) => ( * (createdNoLaterThan == null || a.CreatedDate <= createdNoLaterThan) * && * (createdNoEarlierThan == null || a.CreatedDate >= createdNoEarlierThan) * ), requireAll); * expr = ExpressionHelpers.CombineBinaryExpression(expr, (a) => ( * (lastExecutedNoLaterThan == null || a.LastAttempt <= lastExecutedNoLaterThan) * && * (lastExecutedNoEarlierThan == null || a.LastAttempt >= lastExecutedNoEarlierThan) * ), requireAll); */ var result = expr == null ? new JobMetadataResult[] {} : manager.GetSerializableJobsByCriteria(expr).Select(q => new JobMetadataResult() { ExecutionTime = q.ExecutionTime.ToString(), JobArgs = q.JobArgs.Select(r => new JobParameterDto() { Ordinal = r.Ordinal, Name = r.Name, Type = r.TypeName, Value = r.Value }).ToArray(), JobId = q.JobId, MethodGenericTypes = q.MethodGenericTypes.ToArray(), MethodName = q.MethodName, Queue = q.QueueName, RetryParameters = new JobRetryParameters() { LastAttempt = q.RetryParameters.LastAttempt, RetryCount = q.RetryParameters.RetryCount, MaxRetries = q.RetryParameters.MaxRetries, MinRetryWait = q.RetryParameters.MinRetryWait }, Status = q.Status, TypeExecutedOn = q.TypeExecutedOn }); return(Task.FromResult(result.ToArray())); }
protected MemberExpression GetMemberExpressionFromMemberMaps(string fullName, Expression visitedParentExpr) => ExpressionHelpers.MemberAccesses(fullName, visitedParentExpr);
/// <summary> /// Asynchronously executes the query flow. /// </summary> /// <param name="context"> /// The query context. /// </param> /// <param name="cancellationToken"> /// A cancellation token. /// </param> /// <returns> /// A task that represents the asynchronous /// operation whose result is a query result. /// </returns> public static async Task <QueryResult> QueryAsync( QueryContext context, CancellationToken cancellationToken) { Ensure.NotNull(context, "context"); // process query expression var expression = context.Request.Expression; var visitor = new QueryExpressionVisitor(context); expression = visitor.Visit(expression); // get element type Type elementType = null; var queryType = expression.Type.FindGenericType(typeof(IQueryable <>)); if (queryType != null) { elementType = queryType.GetGenericArguments()[0]; } // append count expression if requested if (elementType != null && context.Request.ShouldReturnCount) { expression = ExpressionHelpers.Count(expression, elementType); elementType = null; // now return type is single int } // execute query QueryResult result; var executor = context.GetHookHandler <IQueryExecutor>(); if (executor == null) { throw new NotSupportedException(Resources.QueryExecutorMissing); } if (elementType != null) { var query = visitor.BaseQuery.Provider.CreateQuery(expression); var method = typeof(IQueryExecutor) .GetMethod("ExecuteQueryAsync") .MakeGenericMethod(elementType); var parameters = new object[] { context, query, cancellationToken }; var task = method.Invoke(executor, parameters) as Task <QueryResult>; result = await task; } else { var method = typeof(IQueryExecutor) .GetMethod("ExecuteSingleAsync") .MakeGenericMethod(expression.Type); var parameters = new object[] { context, visitor.BaseQuery, expression, cancellationToken }; var task = method.Invoke(executor, parameters) as Task <QueryResult>; result = await task; } if (result != null) { result.ResultsSource = visitor.EntitySet; } return(result); }
public void ExpressionChecker_NoException(decimal memberValue) { Assert.DoesNotThrow(() => ExpressionHelpers <Tick> .CheckMemberExpression(x => x.Open, memberValue)); }
public void OnMatch(List <Expression> contentExpressions, PropertyInfo propertyInfo, ParameterExpression paramT, ParameterExpression paramWriter) { var propType = propertyInfo.PropertyType; var elemType = propType.GetElementType(); var typeLenAttr = propertyInfo.GetCustomAttribute <LengthTypeAttribute>(); var customVarAttr = propertyInfo.GetCustomAttribute <CustomVarAttribute>(); var typeLen = typeLenAttr == null ? typeof(short) : typeLenAttr.TypeLen; var isTypeLenCustom = typeLenAttr != null && typeLenAttr.IsCustomVar; var isContentCustom = customVarAttr != null; var isContentPrimitive = PrimitiveTypes.Primitives.Contains(elemType); var miLen = isTypeLenCustom ? typeof(IWriter).GetMethod("WriteCustom").MakeGenericMethod(typeLen) : typeof(IWriter).GetMethod("WriteValue").MakeGenericMethod(typeLen); var paramProp = Expression.Property(paramT, propertyInfo); var paramLen = ExpressionHelpers.GetLengthProperty(paramT, propertyInfo); var i = Expression.Variable(typeof(int), "i"); var callMiLen = Expression.Call(paramWriter, miLen, Expression.Convert(paramLen, typeLen)); contentExpressions.Add(callMiLen); Expression finalExpression; if (!isContentPrimitive) { var dlg = typeof(Serializer <>).MakeGenericType(elemType).GetProperty("SerializeAction"); var content = Expression.Invoke(Expression.Property(null, dlg), Expression.ArrayAccess(paramProp, i), paramWriter); finalExpression = ExpressionHelpers.For(i, Expression.Constant(0), Expression.LessThan(i, paramLen), Expression.PostIncrementAssign(i), content); } else { if (!isContentCustom) { if (elemType == typeof(byte) || elemType == typeof(sbyte)) { var mi = typeof(IWriter).GetMethod("WriteArray").MakeGenericMethod(elemType); finalExpression = Expression.Call(paramWriter, mi, paramProp, paramLen); } else { var mi = typeof(IWriter).GetMethod("WriteValue").MakeGenericMethod(elemType); var content = Expression.Call(paramWriter, mi, Expression.ArrayAccess(paramProp, i)); finalExpression = ExpressionHelpers.For(i, Expression.Constant(0), Expression.LessThan(i, paramLen), Expression.PostIncrementAssign(i), content); } } else { var mi = typeof(IWriter).GetMethod("WriteCustom").MakeGenericMethod(elemType); var content = Expression.Call(paramWriter, mi, Expression.ArrayAccess(paramProp, i)); finalExpression = ExpressionHelpers.For(i, Expression.Constant(0), Expression.LessThan(i, paramLen), Expression.PostIncrementAssign(i), content); } } contentExpressions.Add(finalExpression); }
public void ExpressionChecker_Exception(string memberValue) { Assert.Throws <ArgumentException>(() => ExpressionHelpers <Tick> .CheckMemberExpression(x => x.Open, memberValue)); }
internal Expression CreatePropertyValueExpressionWithFilter(IEdmEntityType elementType, IEdmProperty property, Expression source, FilterClause filterClause) { Contract.Assert(elementType != null); Contract.Assert(property != null); Contract.Assert(source != null); IEdmEntityType declaringType = property.DeclaringType as IEdmEntityType; Contract.Assert(declaringType != null, "only entity types are projected."); // derived property using cast if (elementType != declaringType) { Type castType = EdmLibHelpers.GetClrType(declaringType, _model); if (castType == null) { throw new ODataException(Error.Format(SRResources.MappingDoesNotContainEntityType, declaringType.FullName())); } source = Expression.TypeAs(source, castType); } string propertyName = EdmLibHelpers.GetClrPropertyName(property, _model); Expression propertyValue = Expression.Property(source, propertyName); Type nullablePropertyType = propertyValue.Type.ToNullable(); Expression nullablePropertyValue = ExpressionHelpers.ToNullable(propertyValue); if (filterClause != null && property.Type.IsCollection()) { IEdmTypeReference edmElementType = property.Type.AsCollection().ElementType(); Type clrElementType = EdmLibHelpers.GetClrType(edmElementType, _model); if (clrElementType == null) { throw new ODataException(Error.Format(SRResources.MappingDoesNotContainEntityType, edmElementType.FullName())); } Expression filterSource = typeof(IEnumerable).IsAssignableFrom(source.Type.GetProperty(propertyName).PropertyType) ? Expression.Call( ExpressionHelperMethods.QueryableAsQueryable.MakeGenericMethod(clrElementType), nullablePropertyValue) : nullablePropertyValue; Expression filterPredicate = FilterBinder.Bind( filterClause, clrElementType, _model, _assembliesResolver, _settings); MethodCallExpression filterResult = Expression.Call( ExpressionHelperMethods.QueryableWhereGeneric.MakeGenericMethod(clrElementType), filterSource, filterPredicate); nullablePropertyType = filterResult.Type; if (_settings.HandleNullPropagation == HandleNullPropagationOption.True) { // nullablePropertyValue == null ? null : filterResult nullablePropertyValue = Expression.Condition( test: Expression.Equal(nullablePropertyValue, Expression.Constant(value: null)), ifTrue: Expression.Constant(value: null, type: nullablePropertyType), ifFalse: filterResult); } else { nullablePropertyValue = filterResult; } } if (_settings.HandleNullPropagation == HandleNullPropagationOption.True) { // source == null ? null : propertyValue propertyValue = Expression.Condition( test: Expression.Equal(source, Expression.Constant(value: null)), ifTrue: Expression.Constant(value: null, type: nullablePropertyType), ifFalse: nullablePropertyValue); } else { // need to cast this to nullable as EF would fail while materializing if the property is not nullable and source is null. propertyValue = nullablePropertyValue; } return(propertyValue); }
protected override Expression VisitMethodCall(MethodCallExpression node) { if (ExpressionHelpers.IsQueryMethod(node)) { Logger.Log($"Processing method 'Queryable.{node.Method.Name}'", Indentation.Two); switch (node.Method.Name) { case nameof(Queryable.Any): return(Call(node, new AnyLinqExpression(node, init))); case nameof(Queryable.Count): return(Call(node, new CountLinqExpression(node, init))); case nameof(Queryable.First): case nameof(Queryable.FirstOrDefault): return(Call(node, new FirstLinqExpression(node, init))); case nameof(Queryable.Last): case nameof(Queryable.LastOrDefault): if (strict) { throw Error.UnsupportedOptionalPredicate(node); } return(Call(node, new LastLinqExpression(node, init))); case nameof(Queryable.OrderBy): case nameof(Queryable.OrderByDescending): return(Call(node, new OrderByLinqExpression(node, GetSortDirection(node.Method), init))); case nameof(Queryable.Select): return(Call(node, new SelectLinqExpression(node, init))); case nameof(Queryable.SelectMany): return(Call(node, new SelectManyLinqExpression(node, init))); case nameof(Queryable.Skip): return(Call(node, new SkipLinqExpression(node, init))); case nameof(Queryable.Take): return(Call(node, new TakeLinqExpression(node, init))); case nameof(Queryable.Where): return(Call(node, new WhereLinqExpression(node, init))); default: Logger.Log($"Encountered unsupported method {node.Method.Name}"); if (strict) { throw Error.UnsupportedLinqExpression(node.Method.Name); } var result = base.VisitMethodCall(node); manager.Call(node.Method.Name, null); return(result); } } return(base.VisitMethodCall(node)); }
// new CollectionWrapper<ElementType> { Instance = source.Select((ElementType element) => new Wrapper { }) } private Expression ProjectCollection(Expression source, Type elementType, SelectExpandClause selectExpandClause, IEdmEntityType entityType, IEdmEntitySet entitySet, ExpandedNavigationSelectItem expandedItem) { ParameterExpression element = Expression.Parameter(elementType); // expression // new Wrapper { } Expression projection = ProjectElement(element, selectExpandClause, entityType, entitySet); // expression // (ElementType element) => new Wrapper { } LambdaExpression selector = Expression.Lambda(projection, element); if (expandedItem != null) { source = AddOrderByQueryForSource(source, expandedItem.OrderByOption, elementType); } if (_settings.PageSize.HasValue || (expandedItem != null && (expandedItem.TopOption.HasValue || expandedItem.SkipOption.HasValue))) { // nested paging. Need to apply order by first, and take one more than page size as we need to know // whether the collection was truncated or not while generating next page links. IEnumerable <IEdmStructuralProperty> properties = entityType.Key().Any() ? entityType.Key() : entityType .StructuralProperties() .Where(property => property.Type.IsPrimitive()).OrderBy(property => property.Name); if (expandedItem == null || expandedItem.OrderByOption == null) { bool alreadyOrdered = false; foreach (var prop in properties) { source = ExpressionHelpers.OrderByPropertyExpression(source, prop.Name, elementType, alreadyOrdered); if (!alreadyOrdered) { alreadyOrdered = true; } } } if (expandedItem != null && expandedItem.SkipOption.HasValue) { Contract.Assert(expandedItem.SkipOption.Value <= Int32.MaxValue); source = ExpressionHelpers.Skip(source, (int)expandedItem.SkipOption.Value, elementType, _settings.EnableConstantParameterization); } if (expandedItem != null && expandedItem.TopOption.HasValue) { Contract.Assert(expandedItem.TopOption.Value <= Int32.MaxValue); source = ExpressionHelpers.Take(source, (int)expandedItem.TopOption.Value, elementType, _settings.EnableConstantParameterization); } if (_settings.PageSize.HasValue) { source = ExpressionHelpers.Take(source, _settings.PageSize.Value + 1, elementType, _settings.EnableConstantParameterization); } } // expression // source.Select((ElementType element) => new Wrapper { }) Expression selectedExpresion = Expression.Call(GetSelectMethod(elementType, projection.Type), source, selector); if (_settings.HandleNullPropagation == HandleNullPropagationOption.True) { // source == null ? null : projectedCollection return(Expression.Condition( test: Expression.Equal(source, Expression.Constant(null)), ifTrue: Expression.Constant(null, selectedExpresion.Type), ifFalse: selectedExpresion)); } else { return(selectedExpresion); } }
private LanguageExpression InlineVariables(LanguageExpression original) { var inlined = InlineVariablesRecursive(original); return(ExpressionHelpers.FlattenStringOperations(inlined)); }
public void ToNullable_Returns_SameExpressionIfTypeIsAlreadyNullable() { Expression expression = Expression.Constant("nullable string"); Assert.Same(expression, ExpressionHelpers.ToNullable(expression)); }
/// <summary> /// Pre flattens properties referenced in aggregate clause to avoid generation of nested queries by EF. /// For query like groupby((A), aggregate(B/C with max as Alias1, B/D with max as Alias2)) we need to generate /// .Select( /// $it => new FlattenninWrapper () { /// Source = $it, // Will used in groupby stage /// Container = new { /// Value = $it.B.C /// Next = new { /// Value = $it.B.D /// } /// } /// } /// ) /// Also we need to populate expressions to access B/C and B/D in aggregate stage. It will look like: /// B/C : $it.Container.Value /// B/D : $it.Container.Next.Value /// </summary> /// <param name="query"></param> /// <returns>Query with Select that flattens properties</returns> private IQueryable FlattenReferencedProperties(IQueryable query) { if (_aggregateExpressions != null && _aggregateExpressions.Any(e => e.Method != AggregationMethod.VirtualPropertyCount) && _groupingProperties != null && _groupingProperties.Any() && (FlattenedPropertyContainer == null || !FlattenedPropertyContainer.Any()) ) { var wrapperType = typeof(FlatteningWrapper <>).MakeGenericType(this._elementType); var sourceProperty = wrapperType.GetProperty("Source"); List <MemberAssignment> wta = new List <MemberAssignment>(); wta.Add(Expression.Bind(sourceProperty, this._lambdaParameter)); var aggrregatedPropertiesToFlatten = _aggregateExpressions.Where(e => e.Method != AggregationMethod.VirtualPropertyCount).ToList(); // Generated Select will be stack like, meaning that first property in the list will be deepest one // For example if we add $it.B.C, $it.B.D, select will look like // new { // Value = $it.B.C // Next = new { // Value = $it.B.D // } // } // We are generated references (in currentContainerExpression) from the begining of the Select ($it.Value, then $it.Next.Value etc.) // We have proper match we need insert properties in reverse order // After this // properties = { $it.B.D, $it.B.C} // _preFlattendMAp = { {$it.B.C, $it.Value}, {$it.B.D, $it.Next.Value} } var properties = new NamedPropertyExpression[aggrregatedPropertiesToFlatten.Count]; var aliasIdx = aggrregatedPropertiesToFlatten.Count - 1; var aggParam = Expression.Parameter(wrapperType, "$it"); var currentContainerExpression = Expression.Property(aggParam, GroupByContainerProperty); foreach (var aggExpression in aggrregatedPropertiesToFlatten) { var alias = "Property" + aliasIdx; // We just need unique alias, we aren't going to use it // Add Value = $it.B.C var propAccessExpression = BindAccessor(aggExpression.Expression); var type = propAccessExpression.Type; propAccessExpression = WrapConvert(propAccessExpression); properties[aliasIdx] = new NamedPropertyExpression(Expression.Constant(alias), propAccessExpression); // Save $it.Container.Next.Value for future use UnaryExpression flatAccessExpression = Expression.Convert( Expression.Property(currentContainerExpression, "Value"), type); currentContainerExpression = Expression.Property(currentContainerExpression, "Next"); _preFlattenedMap.Add(aggExpression.Expression, flatAccessExpression); aliasIdx--; } var wrapperProperty = ResultClrType.GetProperty(GroupByContainerProperty); wta.Add(Expression.Bind(wrapperProperty, AggregationPropertyContainer.CreateNextNamedPropertyContainer(properties))); var flatLambda = Expression.Lambda(Expression.MemberInit(Expression.New(wrapperType), wta), _lambdaParameter); query = ExpressionHelpers.Select(query, flatLambda, this._elementType); // We applied flattening let .GroupBy know about it. this._lambdaParameter = aggParam; this._elementType = wrapperType; } return(query); }