Example #1
0
        public void LocalDateTimeOffsetConversion()
        {
            var dto = DateTimeOffset.Now;
            var dt  = WebUtil.ConvertDateTimeOffsetToDateTime(dto);

            dto.DateTime.ShouldBeEquivalentTo(dt, "For local DateTimeOffset values, the value of DateTime within DateTimeOffset must be equal to the result DateTime value");
        }
Example #2
0
        /// <summary>
        /// Converts a primitive value read by ODataMessageReader into a primitive value acceptable by WCF DS.
        /// </summary>
        /// <param name="value">The value reported by ODataMessageReader.</param>
        /// <param name="resourceType">The resource type of the value to read, null if it is an open property value.</param>
        /// <returns>The value converted to the WCF DS value space.</returns>
        protected static object ConvertPrimitiveValue(object value, ref ResourceType resourceType)
        {
            Debug.Assert(resourceType == null || resourceType.ResourceTypeKind == ResourceTypeKind.Primitive, "Only primitive types are supported by this method.");

            // System.Xml.Linq.XElement and System.Data.Linq.Binaries primitive types are not supported by ODataLib directly,
            // so if the property is of one of those types, we need to convert the value to that type here.
            if (value != null)
            {
                Type instanceType;
                if (resourceType == null)
                {
                    resourceType = ResourceType.GetPrimitiveResourceType(value.GetType());
                    instanceType = resourceType.InstanceType;
                }
                else
                {
                    instanceType = resourceType.InstanceType;
                    if (instanceType == typeof(System.Xml.Linq.XElement))
                    {
                        string stringValue = value as string;
                        Debug.Assert(stringValue != null, "If the property is of type System.Xml.Linq.XElement then ODataLib should ahve read it as string.");
                        return(System.Xml.Linq.XElement.Parse(stringValue, System.Xml.Linq.LoadOptions.PreserveWhitespace));
                    }
                    else if (instanceType == typeof(System.Data.Linq.Binary))
                    {
                        byte[] byteArray = value as byte[];
                        Debug.Assert(byteArray != null, "If the property is of type System.Data.Linq.Binary then ODataLib should have read it as byte[].");
                        return(new System.Data.Linq.Binary(byteArray));
                    }
                }

                // It might be the case that store type is DateTime/DateTime? in which case the ResourceType is DateTimeOffset/DateTimeOffset?.
                if (instanceType == typeof(DateTime) || instanceType == typeof(DateTime?))
                {
                    Debug.Assert(value is DateTimeOffset, "Expecting DateTimeOffset for DateTime properties.");
                    value = WebUtil.ConvertDateTimeOffsetToDateTime((DateTimeOffset)value);
                }
            }

            return(value);
        }
Example #3
0
        private Expression PromoteExpression(Expression expr, Type type, bool exact, bool isTypeCast = false)
        {
            Debug.Assert(expr != null, "expr != null");
            Debug.Assert(type != null, "type != null");
            if (expr.Type == type)
            {
                return(expr);
            }

            ConstantExpression ce = null;

            if (type == typeof(DateTime))
            {
                // Sometimes if the property type is DateTime? in provider, we pass the type as DateTimeOffset?
                // to ODataLib and it puts a Convert node to convert DateTimeOffset to DateTimeOffset?. Hence
                // to reach to the constant value, we need to handle the Convert node.
                if (expr.Type == typeof(DateTimeOffset) || expr.Type == typeof(DateTimeOffset?))
                {
                    if (expr.NodeType == ExpressionType.Convert)
                    {
                        ce = ((UnaryExpression)expr).Operand as ConstantExpression;
                    }
                }
            }

            if (ce == null)
            {
                ce = expr as ConstantExpression;
            }

            if (ce != null)
            {
                if (ce == ExpressionUtils.NullLiteral)
                {
                    if (WebUtil.TypeAllowsNull(type))
                    {
                        return(Expression.Constant(null, type));
                    }
                }
                else
                {
                    string text;
                    if (this.literals.TryGetValue(ce, out text))
                    {
                        Type   target = WebUtil.GetNonNullableType(type);
                        object value  = null;
                        if (ce.Type == typeof(string) && (target == typeof(Type) || target == typeof(ResourceType)))
                        {
                            // No qoutes required when the function is a cast
                            if (isTypeCast || WebConvert.TryRemoveQuotes(ref text))
                            {
                                ResourceType resourceType = this.tryResolveResourceType(text);
                                if (resourceType != null)
                                {
                                    if (target == typeof(Type))
                                    {
                                        if (resourceType.CanReflectOnInstanceType)
                                        {
                                            value = resourceType.InstanceType;
                                        }
                                    }
                                    else
                                    {
                                        if (resourceType.CanReflectOnInstanceType == false)
                                        {
                                            value = resourceType;
                                        }
                                    }
                                }
                            }
                        }
                        else if ((type == typeof(DateTime) || type == typeof(DateTime?)) &&
                                 (expr.Type == typeof(DateTimeOffset) || expr.Type == typeof(DateTimeOffset?)))
                        {
                            // Since the URI parser in ODataLib will always convert Constants as DateTimeOffset,
                            // and WCF DS Server supports DateTime clr type, we need to do the conversion whenever required.
                            value = WebUtil.ConvertDateTimeOffsetToDateTime((DateTimeOffset)ce.Value);
                        }
                        else
                        {
                            switch (Type.GetTypeCode(ce.Type))
                            {
                            case TypeCode.Int32:
                            case TypeCode.Int64:
                                value = ParseNumber(text, target);
                                break;

                            case TypeCode.Double:
                                if (target == typeof(decimal))
                                {
                                    value = ParseNumber(text, target);
                                }

                                break;
                            }
                        }

                        if (value != null)
                        {
                            return(Expression.Constant(value, type));
                        }
                    }
                }
            }

            if (IsCompatibleWith(expr.Type, type))
            {
                // (type != typeof(object) || expr.Type.IsValueType) part is added
                // to prevent cast to System.Object from non-value types (objects).
                if (type.IsValueType || exact && (type != typeof(object) || expr.Type.IsValueType))
                {
                    return(Expression.Convert(expr, type));
                }

                return(expr);
            }

            // Allow promotion from nullable to non-nullable by directly accessing underlying value.
            if (WebUtil.IsNullableType(expr.Type) && type.IsValueType)
            {
                Expression valueAccessExpression = Expression.Property(expr, "Value");
                valueAccessExpression = this.PromoteExpression(valueAccessExpression, type, exact, isTypeCast);
                return(valueAccessExpression);
            }

            return(null);
        }