Beispiel #1
0
        private Expression GetPredicateBody(HttpRequestMessage request, ParameterExpression param)
        {
            Expression workingExpr = null;

            var type       = param.Type;
            var queryPairs = request.GetQueryNameValuePairs();

            foreach (var queryPair in queryPairs)
            {
                if (String.IsNullOrWhiteSpace(queryPair.Key))
                {
                    continue;
                }

                var prop = _modelManager.GetPropertyForJsonKey(type, queryPair.Key);

                if (prop != null)
                {
                    var propertyType = prop.PropertyType;

                    var queryValue = queryPair.Value;
                    if (string.IsNullOrWhiteSpace(queryValue))
                    {
                        queryValue = null;
                    }

                    Expression expr = null;
                    if (propertyType == typeof(String))
                    {
                        if (String.IsNullOrWhiteSpace(queryValue))
                        {
                            Expression propertyExpr = Expression.Property(param, prop);
                            expr = Expression.Equal(propertyExpr, Expression.Constant(null));
                        }
                        else
                        {
                            Expression propertyExpr = Expression.Property(param, prop);
                            expr = Expression.Equal(propertyExpr, Expression.Constant(queryValue));
                        }
                    }
                    else if (propertyType == typeof(Boolean))
                    {
                        bool value;
                        expr = bool.TryParse(queryValue, out value)
                            ? GetPropertyExpression(value, prop, param)
                            : Expression.Constant(false);
                    }
                    else if (propertyType == typeof(Boolean?))
                    {
                        bool tmp;
                        var  value = bool.TryParse(queryValue, out tmp) ? tmp : (bool?)null;
                        expr = GetPropertyExpression(value, prop, param);
                    }
                    else if (propertyType == typeof(SByte))
                    {
                        SByte value;
                        expr = SByte.TryParse(queryValue, out value)
                            ? GetPropertyExpression(value, prop, param)
                            : Expression.Constant(false);
                    }
                    else if (propertyType == typeof(SByte?))
                    {
                        SByte tmp;
                        var   value = SByte.TryParse(queryValue, out tmp) ? tmp : (SByte?)null;
                        expr = GetPropertyExpression(value, prop, param);
                    }
                    else if (propertyType == typeof(Byte))
                    {
                        Byte value;
                        expr = Byte.TryParse(queryValue, out value)
                            ? GetPropertyExpression(value, prop, param)
                            : Expression.Constant(false);
                    }
                    else if (propertyType == typeof(Byte?))
                    {
                        Byte tmp;
                        var  value = Byte.TryParse(queryValue, out tmp) ? tmp : (Byte?)null;
                        expr = GetPropertyExpression(value, prop, param);
                    }
                    else if (propertyType == typeof(Int16))
                    {
                        Int16 value;
                        expr = Int16.TryParse(queryValue, out value)
                            ? GetPropertyExpression(value, prop, param)
                            : Expression.Constant(false);
                    }
                    else if (propertyType == typeof(Int16?))
                    {
                        Int16 tmp;
                        var   value = Int16.TryParse(queryValue, out tmp) ? tmp : (Int16?)null;
                        expr = GetPropertyExpression(value, prop, param);
                    }
                    else if (propertyType == typeof(UInt16))
                    {
                        UInt16 value;
                        expr = UInt16.TryParse(queryValue, out value)
                            ? GetPropertyExpression(value, prop, param)
                            : Expression.Constant(false);
                    }
                    else if (propertyType == typeof(UInt16?))
                    {
                        UInt16 tmp;
                        var    value = UInt16.TryParse(queryValue, out tmp) ? tmp : (UInt16?)null;
                        expr = GetPropertyExpression(value, prop, param);
                    }
                    else if (propertyType == typeof(Int32))
                    {
                        Int32 value;
                        expr = Int32.TryParse(queryValue, out value)
                            ? GetPropertyExpression(value, prop, param)
                            : Expression.Constant(false);
                    }
                    else if (propertyType == typeof(Int32?))
                    {
                        Int32 tmp;
                        var   value = Int32.TryParse(queryValue, out tmp) ? tmp : (Int32?)null;
                        expr = GetPropertyExpression(value, prop, param);
                    }
                    else if (propertyType == typeof(UInt32))
                    {
                        UInt32 value;
                        expr = UInt32.TryParse(queryValue, out value)
                            ? GetPropertyExpression(value, prop, param)
                            : Expression.Constant(false);
                    }
                    else if (propertyType == typeof(UInt32?))
                    {
                        UInt32 tmp;
                        var    value = UInt32.TryParse(queryValue, out tmp) ? tmp : (UInt32?)null;
                        expr = GetPropertyExpression(value, prop, param);
                    }
                    else if (propertyType == typeof(Int64))
                    {
                        Int64 value;
                        expr = Int64.TryParse(queryValue, out value)
                            ? GetPropertyExpression(value, prop, param)
                            : Expression.Constant(false);
                    }
                    else if (propertyType == typeof(Int64?))
                    {
                        Int64 tmp;
                        var   value = Int64.TryParse(queryValue, out tmp) ? tmp : (Int64?)null;
                        expr = GetPropertyExpression(value, prop, param);
                    }
                    else if (propertyType == typeof(UInt64))
                    {
                        UInt64 value;
                        expr = UInt64.TryParse(queryValue, out value)
                            ? GetPropertyExpression(value, prop, param)
                            : Expression.Constant(false);
                    }
                    else if (propertyType == typeof(UInt64?))
                    {
                        UInt64 tmp;
                        var    value = UInt64.TryParse(queryValue, out tmp) ? tmp : (UInt64?)null;
                        expr = GetPropertyExpression(value, prop, param);
                    }
                    else if (propertyType == typeof(Single))
                    {
                        Single value;
                        expr = Single.TryParse(queryValue, out value)
                            ? GetPropertyExpression(value, prop, param)
                            : Expression.Constant(false);
                    }
                    else if (propertyType == typeof(Single?))
                    {
                        Single tmp;
                        var    value = Single.TryParse(queryValue, out tmp) ? tmp : (Single?)null;
                        expr = GetPropertyExpression(value, prop, param);
                    }
                    else if (propertyType == typeof(Double))
                    {
                        Double value;
                        expr = Double.TryParse(queryValue, out value)
                            ? GetPropertyExpression(value, prop, param)
                            : Expression.Constant(false);
                    }
                    else if (propertyType == typeof(Double?))
                    {
                        Double tmp;
                        var    value = Double.TryParse(queryValue, out tmp) ? tmp : (Double?)null;
                        expr = GetPropertyExpression(value, prop, param);
                    }
                    else if (propertyType == typeof(Decimal))
                    {
                        Decimal value;
                        expr = Decimal.TryParse(queryValue, out value)
                            ? GetPropertyExpression(value, prop, param)
                            : Expression.Constant(false);
                    }
                    else if (propertyType == typeof(Decimal?))
                    {
                        Decimal tmp;
                        var     value = Decimal.TryParse(queryValue, out tmp) ? tmp : (Decimal?)null;
                        expr = GetPropertyExpression(value, prop, param);
                    }
                    else if (propertyType == typeof(DateTime))
                    {
                        DateTime value;
                        expr = DateTime.TryParse(queryValue, out value)
                            ? GetPropertyExpression(value, prop, param)
                            : Expression.Constant(false);
                    }
                    else if (propertyType == typeof(DateTime?))
                    {
                        DateTime tmp;
                        var      value = DateTime.TryParse(queryValue, out tmp) ? tmp : (DateTime?)null;
                        expr = GetPropertyExpression(value, prop, param);
                    }
                    else if (propertyType == typeof(DateTimeOffset))
                    {
                        DateTimeOffset value;
                        expr = DateTimeOffset.TryParse(queryValue, out value)
                            ? GetPropertyExpression <DateTimeOffset>(value, prop, param)
                            : Expression.Constant(false);
                    }
                    else if (propertyType == typeof(DateTimeOffset?))
                    {
                        DateTimeOffset tmp;
                        var            value = DateTimeOffset.TryParse(queryValue, out tmp) ? tmp : (DateTimeOffset?)null;
                        expr = GetPropertyExpression(value, prop, param);
                    }
                    else if (propertyType.IsEnum)
                    {
                        int value;
                        expr = (int.TryParse(queryValue, out value) && Enum.IsDefined(propertyType, value))
                            ? GetEnumPropertyExpression(value, prop, param)
                            : Expression.Constant(false);
                    }
                    else if (propertyType.IsGenericType && propertyType.GetGenericTypeDefinition() == typeof(Nullable <>) &&
                             propertyType.GenericTypeArguments[0].IsEnum)
                    {
                        int tmp;
                        var value = int.TryParse(queryValue, out tmp) ? tmp : (int?)null;
                        expr = GetEnumPropertyExpression(value, prop, param);
                    }
                    else
                    {
                        // See if it is a relationship property
                        if (_modelManager.IsSerializedAsMany(propertyType))
                        {
                            var          elementType = _modelManager.GetElementType(propertyType);
                            PropertyInfo relatedIdProperty;
                            try
                            {
                                relatedIdProperty = _modelManager.GetIdProperty(elementType);
                            }
                            catch (InvalidOperationException)
                            {
                                relatedIdProperty = null;
                            }

                            if (relatedIdProperty != null)
                            {
                                var propertyExpr = Expression.Property(param, prop);

                                if (string.IsNullOrWhiteSpace(queryValue))
                                {
                                    var leftExpr = Expression.Equal(propertyExpr, Expression.Constant(null));

                                    var asQueryableCallExpr = Expression.Call(
                                        typeof(Queryable),
                                        "AsQueryable",
                                        new[] { elementType },
                                        propertyExpr);
                                    var anyCallExpr = Expression.Call(
                                        typeof(Queryable),
                                        "Any",
                                        new[] { elementType },
                                        asQueryableCallExpr);
                                    var rightExpr = Expression.Not(anyCallExpr);

                                    expr = Expression.OrElse(leftExpr, rightExpr);
                                }
                                else
                                {
                                    var leftExpr = Expression.NotEqual(propertyExpr, Expression.Constant(null));

                                    var idValue  = queryValue.Trim();
                                    var idExpr   = Expression.Constant(idValue);
                                    var anyParam = Expression.Parameter(elementType);
                                    var relatedIdPropertyExpr         = Expression.Property(anyParam, relatedIdProperty);
                                    var relatedIdPropertyEqualsIdExpr = Expression.Equal(relatedIdPropertyExpr, idExpr);
                                    var anyPredicateExpr    = Expression.Lambda(relatedIdPropertyEqualsIdExpr, anyParam);
                                    var asQueryableCallExpr = Expression.Call(
                                        typeof(Queryable),
                                        "AsQueryable",
                                        new[] { elementType },
                                        propertyExpr);
                                    var rightExpr = Expression.Call(
                                        typeof(Queryable),
                                        "Any",
                                        new[] { elementType },
                                        asQueryableCallExpr,
                                        anyPredicateExpr);

                                    expr = Expression.AndAlso(leftExpr, rightExpr);
                                }
                            }
                        }
                        else
                        {
                            PropertyInfo relatedIdProperty;
                            try
                            {
                                relatedIdProperty = _modelManager.GetIdProperty(propertyType);
                            }
                            catch (InvalidOperationException)
                            {
                                relatedIdProperty = null;
                            }

                            if (relatedIdProperty != null)
                            {
                                var propertyExpr = Expression.Property(param, prop);

                                if (string.IsNullOrWhiteSpace(queryValue))
                                {
                                    expr = Expression.Equal(propertyExpr, Expression.Constant(null));
                                }
                                else
                                {
                                    var leftExpr = Expression.NotEqual(propertyExpr, Expression.Constant(null));

                                    var idValue = queryValue.Trim();
                                    var idExpr  = Expression.Constant(idValue);
                                    var relatedIdPropertyExpr = Expression.Property(propertyExpr, relatedIdProperty);
                                    var rightExpr             = Expression.Equal(relatedIdPropertyExpr, idExpr);

                                    expr = Expression.AndAlso(leftExpr, rightExpr);
                                }
                            }
                        }
                    }

                    if (expr == null)
                    {
                        expr = Expression.Constant(true);
                    }

                    workingExpr = workingExpr == null ? expr : Expression.AndAlso(workingExpr, expr);
                }
            }

            return(workingExpr ?? Expression.Constant(true)); // No filters, so return everything
        }
        public object Deserialize(Type objectType, Stream readStream, JsonReader reader, JsonSerializer serializer)
        {
            object retval = Activator.CreateInstance(objectType);

            if (reader.TokenType != JsonToken.StartObject)
            {
                throw new JsonReaderException(String.Format("Expected JsonToken.StartObject, got {0}", reader.TokenType.ToString()));
            }
            reader.Read(); // Burn the StartObject token
            do
            {
                if (reader.TokenType == JsonToken.PropertyName)
                {
                    string       value = (string)reader.Value;
                    PropertyInfo prop;
                    if (value == "links")
                    {
                        reader.Read(); // burn the PropertyName token
                        //TODO: linked resources (Done??)
                        DeserializeLinkedResources(retval, readStream, reader, serializer);
                    }
                    else if ((prop = _modelManager.GetPropertyForJsonKey(objectType, value)) != null)
                    {
                        reader.Read(); // burn the PropertyName token
                        //TODO: Embedded would be dropped here!
                        if (!CanWriteTypeAsPrimitive(prop.PropertyType))
                        {
                            continue;                                              // These aren't supposed to be here, they're supposed to be in "links"!
                        }
                        object propVal;
                        if (prop.PropertyType == typeof(string) &&
                            prop.GetCustomAttributes().Any(attr => attr is SerializeStringAsRawJsonAttribute))
                        {
                            if (reader.TokenType == JsonToken.Null)
                            {
                                propVal = null;
                            }
                            else
                            {
                                var token      = JToken.Load(reader);
                                var rawPropVal = token.ToString();
                                propVal = JsonHelpers.MinifyJson(rawPropVal);
                            }
                        }
                        else
                        {
                            propVal = DeserializePrimitive(prop.PropertyType, reader);
                        }

                        prop.SetValue(retval, propVal, null);

                        // Tell the MetadataManager that we deserialized this property
                        MetadataManager.Instance.SetMetaForProperty(retval, prop, true);

                        // pop the value off the reader, so we catch the EndObject token below!.
                        reader.Read();
                    }
                    else
                    {
                        // Unexpected/unknown property--Skip the propertyname and its value
                        reader.Skip();
                        if (reader.TokenType == JsonToken.StartArray || reader.TokenType == JsonToken.StartObject)
                        {
                            reader.Skip();
                        }
                        else
                        {
                            reader.Read();
                        }
                    }
                }
            } while (reader.TokenType != JsonToken.EndObject);
            reader.Read(); // burn the EndObject token before returning back up the call stack

            /*
             * // Suss out all the relationship members, and which ones have what cardinality...
             * IEnumerable<PropertyInfo> relations = (
             *  from prop in objectType.GetProperties()
             *  where !CanWriteTypeAsPrimitive(prop.PropertyType)
             *  && prop.GetCustomAttributes(true).Any(attribute => attribute is System.Runtime.Serialization.DataMemberAttribute)
             *  select prop
             *  );
             * IEnumerable<PropertyInfo> hasManys = relations.Where(prop => typeof(IEnumerable<object>).IsAssignableFrom(prop.PropertyType));
             * IEnumerable<PropertyInfo> belongsTos = relations.Where(prop => !typeof(IEnumerable<object>).IsAssignableFrom(prop.PropertyType));
             *
             * JObject links = (JObject)jo["links"];
             *
             * // Lets deal with belongsTos first, that should be simpler...
             * foreach (PropertyInfo prop in belongsTos)
             * {
             *  if (links == null) break; // Well, apparently we don't have any data for the relationships!
             *
             *  string btId = (string)links[_modelManager.GetJsonKeyForProperty(prop)];
             *  if (btId == null)
             *  {
             *      prop.SetValue(retval, null, null); // Important that we set--the value may have been cleared!
             *      continue; // breaking early!
             *  }
             *  Type relType = prop.PropertyType;
             *  //if (typeof(EntityObject).IsAssignableFrom(relType))
             *  if (resolver.CanIncludeTypeAsObject(relType))
             *  {
             *      prop.SetValue(retval, resolver.GetById(relType, btId), null);
             *      //throw new ApplicationException(String.Format("Could not assign BelongsTo property \"{0}\" on object of type {1} by ID {2} because no object of type {3} could be retrieved by that ID.", prop.Name, objectType, btId, prop.PropertyType));
             *  }
             * }
             */

            return(retval);
        }