public override LambdaExpression VisitValPathOperatorExp(ScimFilterParser.ValPathOperatorExpContext context) { var argument = Expression.Parameter(typeof(TResource)); var attrPathExpression = Visit(context.attrPath()); var operatorToken = context.COMPAREOPERATOR().GetText().ToLower(); var valueToken = context.VALUE().GetText().Trim('"'); var isEnumerable = attrPathExpression.ReturnType.IsNonStringEnumerable(); var left = Expression.TryCatch( Expression.Block(Expression.Invoke(attrPathExpression, argument)), Expression.Catch( typeof(NullReferenceException), Expression.Constant(attrPathExpression.ReturnType.GetDefaultValue(), attrPathExpression.ReturnType) )); if (isEnumerable && attrPathExpression.ReturnType.IsGenericType && typeof(MultiValuedAttribute).IsAssignableFrom(attrPathExpression.ReturnType.GetGenericArguments()[0])) { // we're filtering an enumerable of multivaluedattribute without a sub-attribute // therefore, we default to evaluating the .Value member var multiValuedAttributeType = attrPathExpression.ReturnType.GetGenericArguments()[0]; var multiValuedAttribute = Expression.Parameter(multiValuedAttributeType); var valueAttribute = multiValuedAttributeType.GetProperty("Value", BindingFlags.Public | BindingFlags.Instance); var valueExpression = Expression.TryCatch( Expression.Block(Expression.Property(multiValuedAttribute, valueAttribute)), Expression.Catch( typeof(NullReferenceException), Expression.Constant(valueAttribute.PropertyType.GetDefaultValue(), valueAttribute.PropertyType)) ); var valueLambda = Expression.Lambda( CreateBinaryExpression(valueExpression, operatorToken, valueToken), multiValuedAttribute); var anyMethod = MethodCache["any"].MakeGenericMethod(multiValuedAttributeType); var anyPredicate = Expression.TryCatch( Expression.Block( Expression.Call( anyMethod, new List <Expression> { left, valueLambda })), Expression.Catch(typeof(ArgumentNullException), Expression.Constant(false))); return(Expression.Lambda(anyPredicate, argument)); } return(Expression.Lambda <Func <TResource, bool> >( CreateBinaryExpression(left, operatorToken, valueToken), argument)); }
public override LambdaExpression VisitValPathOperatorExp(ScimFilterParser.ValPathOperatorExpContext context) { var propertyNameToken = context.FIELD().GetText(); var operatorToken = context.COMPAREOPERATOR().GetText().ToLower(); var valueToken = context.VALUE().GetText().Trim('"'); var property = PropertyCache .GetOrAdd( typeof(TResource), type => type.GetProperties(BindingFlags.Public | BindingFlags.Instance) .ToDictionary(pi => pi.Name, pi => pi, StringComparer.OrdinalIgnoreCase))[propertyNameToken]; if (property == null) { throw new Exception("ERROR"); // TODO: (DG) make proper error } var isEnumerable = property.PropertyType.IsNonStringEnumerable(); var argument = Expression.Parameter(typeof(TResource)); var left = Expression.TryCatch( Expression.Block(Expression.Property(argument, property)), Expression.Catch( typeof(NullReferenceException), Expression.Constant(property.PropertyType.GetDefaultValue(), property.PropertyType)) ); if (isEnumerable && property.PropertyType.IsGenericType && typeof(MultiValuedAttribute).IsAssignableFrom(property.PropertyType.GetGenericArguments()[0])) { // we're filtering an enumerable of multivaluedattribute without a sub-attribute // therefore, we default to evaluating the .Value member var multiValuedAttributeType = property.PropertyType.GetGenericArguments()[0]; var multiValuedAttribute = Expression.Parameter(multiValuedAttributeType); var valueAttribute = multiValuedAttributeType.GetProperty("Value", BindingFlags.Public | BindingFlags.Instance); var valueExpression = Expression.TryCatch( Expression.Block(Expression.Property(multiValuedAttribute, valueAttribute)), Expression.Catch( typeof(NullReferenceException), Expression.Constant(valueAttribute.PropertyType.GetDefaultValue(), valueAttribute.PropertyType)) ); var valueLambda = Expression.Lambda( CreateBinaryExpression(valueExpression, valueAttribute, operatorToken, valueToken), multiValuedAttribute); var anyMethod = MethodCache["any"].MakeGenericMethod(multiValuedAttributeType); var anyPredicate = Expression.TryCatch( Expression.Block( Expression.Call( anyMethod, new List <Expression> { left, valueLambda })), Expression.Catch(typeof(ArgumentNullException), Expression.Constant(false))); return(Expression.Lambda(anyPredicate, argument)); } return(Expression.Lambda <Func <TResource, bool> >( CreateBinaryExpression(left, property, operatorToken, valueToken), argument)); }