Exemple #1
0
        /// <summary>
        /// Gets the attributes associated with the specified member.
        /// </summary>
        /// <param name="memberInfo">The reflection member.</param>
        /// <param name="inherit">if set to <c>true</c> includes inherited attributes.</param>
        /// <returns>An enumeration of <see cref="Attribute"/>.</returns>
        public virtual List <Attribute> GetAttributes(MemberInfo memberInfo, bool inherit = true)
        {
            var key = new MemberInfoKey(memberInfo, inherit);

            lock (globalLock)
            {
                // Use a cache of attributes
                List <Attribute> attributes;
                if (cachedAttributes.TryGetValue(key, out attributes))
                {
                    return(attributes);
                }

                // Else retrieve all default attributes
                var defaultAttributes = Attribute.GetCustomAttributes(memberInfo, inherit);
                attributes = defaultAttributes.ToList();

                // And add registered attributes
                List <Attribute> registered;
                if (registeredAttributes.TryGetValue(memberInfo, out registered))
                {
                    attributes.AddRange(registered);
                }

                // Add to the cache
                cachedAttributes.Add(key, attributes);
                return(attributes);
            }
        }
Exemple #2
0
        /// <summary>
        /// Gets the attributes associated with the specified member.
        /// </summary>
        /// <param name="memberInfo">The reflection member.</param>
        /// <param name="inherit">if set to <c>true</c> includes inherited attributes.</param>
        /// <returns>An enumeration of <see cref="Attribute"/>.</returns>
        public virtual IReadOnlyCollection <Attribute> GetAttributes(MemberInfo memberInfo, bool inherit = true)
        {
            var key = new MemberInfoKey(memberInfo, inherit);

            // Use a cache of attributes
            IReadOnlyCollection <Attribute> attributes;

            lock (cachedAttributes)
            {
                if (cachedAttributes.TryGetValue(key, out attributes))
                {
                    return(attributes);
                }

                // Else retrieve all default attributes
                var defaultAttributes = Attribute.GetCustomAttributes(memberInfo, inherit);
                var attributesToCache = defaultAttributes.ToList();

                // And add registered attributes
                List <Attribute> registered;
                if (registeredAttributes.TryGetValue(memberInfo, out registered))
                {
                    attributesToCache.AddRange(registered);
                }

                attributes = attributesToCache.AsReadOnly();

                // Add to the cache
                cachedAttributes.Add(key, attributes);
            }

            return(attributes);
        }
        /// <summary>
        /// Gets the attributes associated with the specified member.
        /// </summary>
        /// <param name="memberInfo">The reflection member.</param>
        /// <param name="inherit">if set to <c>true</c> includes inherited attributes.</param>
        /// <returns>An enumeration of <see cref="Attribute"/>.</returns>
        public virtual List <Attribute> GetAttributes(MemberInfo memberInfo, bool inherit = true)
        {
            var key = new MemberInfoKey(memberInfo, inherit);

            // Use a cache of attributes
            List <Attribute> attributes;

            lock (lockObject)
            {
                if (cachedAttributes.TryGetValue(key, out attributes))
                {
                    return(attributes);
                }

                // Else retrieve all default attributes
                var defaultAttributes = Attribute.GetCustomAttributes(memberInfo, inherit);
                IEnumerable <Attribute> attributesToCache = defaultAttributes;

                // And add registered attributes
                List <Attribute> registered;
                if (registeredAttributes.TryGetValue(memberInfo, out registered))
                {
                    // Remove "real" attributes overridden by manually registered attributes
                    attributesToCache = registered.Concat(defaultAttributes.Where(x => GetUsage(x).AllowMultiple || registered.All(y => y.GetType() != x.GetType())));
                }

                attributes = attributesToCache.ToList();

                // Add to the cache
                cachedAttributes.Add(key, attributes);
            }

            return(attributes);
        }
Exemple #4
0
        public static AttributeCollection GetRawAttributes(EventInfo eventInfo)
        {
            if (eventInfo == null)
            {
                throw new ArgumentNullException("eventInfo");
            }

            string        name          = eventInfo.Name;
            Type          declaringType = eventInfo.DeclaringType.UnderlyingSystemType;
            Type          memberType    = eventInfo.EventHandlerType.UnderlyingSystemType;
            MemberInfoKey memberInfoKey = new MemberInfoKey(name, declaringType.TypeHandle, memberType.TypeHandle);

            Dictionary <MemberInfoKey, AttributeCollection> attributesCache = DomainTypeDescriptor.EventInfoAttributesCache;
            AttributeCollection attributeCollection;

            if (!attributesCache.TryGetValue(memberInfoKey, out attributeCollection))
            {
                lock (attributesCache)
                {
                    if (!attributesCache.TryGetValue(memberInfoKey, out attributeCollection))
                    {
                        attributesCache[memberInfoKey] = attributeCollection =
                            TypeDescriptor.CreateEvent(declaringType, name, memberType, null).Attributes;
                    }
                }
            }
            return(attributeCollection);
        }
Exemple #5
0
        public static AttributeCollection GetRawAttributes(PropertyInfo propertyInfo)
        {
            if (propertyInfo == null)
            {
                throw new ArgumentNullException("propertyInfo");
            }

            string        name          = propertyInfo.Name;
            Type          declaringType = propertyInfo.DeclaringType.UnderlyingSystemType;
            Type          memberType    = propertyInfo.PropertyType.UnderlyingSystemType;
            MemberInfoKey memberInfoKey = new MemberInfoKey(name, declaringType.TypeHandle, memberType.TypeHandle);

            Dictionary <MemberInfoKey, AttributeCollection> attributesCache = DomainTypeDescriptor.PropertyInfoAttributesCache;
            AttributeCollection attributeCollection;

            if (!attributesCache.TryGetValue(memberInfoKey, out attributeCollection) || attributeCollection == null)
            {
                lock (attributesCache)
                {
                    // If there is an entry in the cache for this property, then the dependencies for it
                    // have already been calculated previously.
                    bool dependenciesAlreadyCalculated = attributesCache.TryGetValue(memberInfoKey, out attributeCollection);
                    if (!dependenciesAlreadyCalculated || attributeCollection == null)
                    {
                        // This property either hasn't had its attributes retrieved, or one of the types on which
                        // it is dependent has been refreshed since the attributes were last retrieved. Either way,
                        // we need to recalculate the attributes for this property.
                        attributesCache[memberInfoKey] = attributeCollection =
                            TypeDescriptor.CreateProperty(declaringType, name, memberType, null).Attributes;

                        if (!dependenciesAlreadyCalculated)
                        {
                            // Since we haven't calculated the dependencies of this property before, we need to do
                            // so now so that we know what properties to update when the TypeDescriptor.Refreshed
                            // event is raised.
                            Dictionary <RuntimeTypeHandle, List <MemberInfoKey> > dependencies = DomainTypeDescriptor.PropertyTypeDependencies;
                            while (memberType != null)
                            {
                                RuntimeTypeHandle    memberTypeHandle = memberType.TypeHandle;
                                List <MemberInfoKey> dependentProperties;
                                if (!dependencies.TryGetValue(memberTypeHandle, out dependentProperties))
                                {
                                    dependencies[memberTypeHandle] = dependentProperties = new List <MemberInfoKey>();
                                }

                                dependentProperties.Add(memberInfoKey);
                                memberType = memberType.BaseType;
                            }
                        }
                    }
                }
            }
            return(attributeCollection);
        }
        public void CorrectlyMatchesInstanceMemberInfos()
        {
            Dictionary <MethodInfo, MemberInfoKey> instanceMethods =
                new Dictionary <MethodInfo, MemberInfoKey>()
            {
                { FindInstanceMethod(typeof(string), "ToLower"),
                  new MemberInfoKey(typeof(string), "ToLower", true, true) },
                { FindInstanceMethod(typeof(string), "ToLowerInvariant"),
                  new MemberInfoKey(typeof(string), "ToLowerInvariant", true, true) },
                { FindInstanceMethod(typeof(string), "ToUpper"),
                  new MemberInfoKey(typeof(string), "ToUpper", true, true) },
                { FindInstanceMethod(typeof(string), "ToUpperInvariant"),
                  new MemberInfoKey(typeof(string), "ToUpperInvariant", true, true) },
                { FindInstanceMethod(typeof(string), "Trim"),
                  new MemberInfoKey(typeof(string), "Trim", true, true) },
                { FindInstanceMethod(typeof(string), "StartsWith", typeof(string)),
                  new MemberInfoKey(typeof(string), "StartsWith", true, true, typeof(string)) },
                { FindInstanceMethod(typeof(string), "EndsWith", typeof(string)),
                  new MemberInfoKey(typeof(string), "EndsWith", true, true, typeof(string)) },
                { FindInstanceMethod(typeof(string), "IndexOf", typeof(string)),
                  new MemberInfoKey(typeof(string), "IndexOf", true, true, typeof(string)) },
                { FindInstanceMethod(typeof(string), "IndexOf", typeof(char)),
                  new MemberInfoKey(typeof(string), "IndexOf", true, true, typeof(char)) },
                { FindInstanceMethod(typeof(string), "Contains", typeof(string)),
                  new MemberInfoKey(typeof(string), "Contains", true, true, typeof(string)) },
                { FindInstanceMethod(typeof(string), "Replace", typeof(string), typeof(string)),
                  new MemberInfoKey(typeof(string), "Replace", true, true, typeof(string), typeof(string)) },
                { FindInstanceMethod(typeof(string), "Replace", typeof(char), typeof(char)),
                  new MemberInfoKey(typeof(string), "Replace", true, true, typeof(char), typeof(char)) },
                { FindInstanceMethod(typeof(string), "Substring", typeof(int)),
                  new MemberInfoKey(typeof(string), "Substring", true, true, typeof(int)) },
                { FindInstanceMethod(typeof(string), "Substring", typeof(int), typeof(int)),
                  new MemberInfoKey(typeof(string), "Substring", true, true, typeof(int), typeof(int)) },
            };

            foreach (MethodInfo key in instanceMethods.Keys)
            {
                foreach (var pair in instanceMethods)
                {
                    MemberInfoKey other = new MemberInfoKey(key);
                    if (key == pair.Key)
                    {
                        Assert.IsTrue(pair.Value.Equals(other));
                    }
                    else
                    {
                        Assert.IsFalse(pair.Value.Equals(other));
                    }
                }
            }
        }
Exemple #7
0
        /// <summary>
        /// Gets the attributes associated with the specified member.
        /// </summary>
        /// <param name="memberInfo">The reflection member.</param>
        /// <param name="inherit">if set to <c>true</c> includes inherited attributes.</param>
        /// <returns>An enumeration of <see cref="Attribute"/>.</returns>
        public virtual List <Attribute> GetAttributes(MemberInfo memberInfo, bool inherit = true)
        {
            var key = new MemberInfoKey(memberInfo, inherit);

            lock (globalLock)
            {
                // Use a cache of attributes
                List <Attribute> attributes;
                if (cachedAttributes.TryGetValue(key, out attributes))
                {
                    return(attributes);
                }

                // Else retrieve all default attributes
                var defaultAttributes = memberInfo.GetCustomAttributes(inherit).OfType <Attribute>();
                attributes = defaultAttributes.ToList();

                // And add registered attributes
                List <Attribute> registered;
                if (registeredAttributes.TryGetValue(memberInfo, out registered))
                {
                    attributes.AddRange(registered);
                }

                // Allow to remap attributes
                if (AttributeRemap != null)
                {
                    for (int i = 0; i < attributes.Count; i++)
                    {
                        attributes[i] = AttributeRemap(attributes[i]);
                    }
                }

                // Add to the cache
                cachedAttributes.Add(key, attributes);
                return(attributes);
            }
        }
        public void CorrectlyMatchesPropertyInfos()
        {
            Dictionary <MemberInfo, MemberInfoKey> instanceProperties =
                new Dictionary <MemberInfo, MemberInfoKey>()
            {
                { FindInstanceProperty(typeof(string), "Length"),
                  new MemberInfoKey(typeof(string), "Length", false, true) },
                { FindInstanceProperty(typeof(DateTime), "Day"),
                  new MemberInfoKey(typeof(DateTime), "Day", false, true) },
                { FindInstanceProperty(typeof(DateTime), "Month"),
                  new MemberInfoKey(typeof(DateTime), "Month", false, true) },
                { FindInstanceProperty(typeof(DateTime), "Year"),
                  new MemberInfoKey(typeof(DateTime), "Year", false, true) },
                { FindInstanceProperty(typeof(DateTime), "Hour"),
                  new MemberInfoKey(typeof(DateTime), "Hour", false, true) },
                { FindInstanceProperty(typeof(DateTime), "Minute"),
                  new MemberInfoKey(typeof(DateTime), "Minute", false, true) },
                { FindInstanceProperty(typeof(DateTime), "Second"),
                  new MemberInfoKey(typeof(DateTime), "Second", false, true) },
            };

            foreach (MemberInfo key in instanceProperties.Keys)
            {
                foreach (var pair in instanceProperties)
                {
                    MemberInfoKey other = new MemberInfoKey(key);
                    if (key == pair.Key)
                    {
                        Assert.IsTrue(pair.Value.Equals(other));
                    }
                    else
                    {
                        Assert.IsFalse(pair.Value.Equals(other));
                    }
                }
            }
        }
        public void CorrectlyMatchesStaticMemberInfos()
        {
            Dictionary <MethodInfo, MemberInfoKey> staticMethods =
                new Dictionary <MethodInfo, MemberInfoKey>
            {
                { FindStaticMethod(typeof(Math), "Floor", typeof(double)),
                  new MemberInfoKey(typeof(Math), "Floor", true, false, typeof(double)) },
                { FindStaticMethod(typeof(Math), "Ceiling", typeof(double)),
                  new MemberInfoKey(typeof(Math), "Ceiling", true, false, typeof(double)) },
                { FindStaticMethod(typeof(Math), "Round", typeof(double)),
                  new MemberInfoKey(typeof(Math), "Round", true, false, typeof(double)) },
                { FindStaticMethod(typeof(string), "Concat", typeof(string), typeof(string)),
                  new MemberInfoKey(typeof(string), "Concat", true, false, typeof(string), typeof(string)) }
            };

            // Windows 8 supports decimal.Floor(), decimal.Ceiling() and decimal.Round(), but Windows Phone does not,
            // so we have to ensure these method infos exist before we add them.
            MethodInfo possibleFloorMethod = FindStaticMethod(typeof(Decimal), "Floor", typeof(decimal));

            if (possibleFloorMethod != null)
            {
                staticMethods.Add(possibleFloorMethod,
                                  new MemberInfoKey(typeof(Decimal), "Floor", true, false, typeof(decimal)));
            }

            MethodInfo possibleCeilingMethod = FindStaticMethod(typeof(Decimal), "Ceiling", typeof(decimal));

            if (possibleCeilingMethod != null)
            {
                staticMethods.Add(possibleCeilingMethod,
                                  new MemberInfoKey(typeof(Decimal), "Ceiling", true, false, typeof(decimal)));
            }

            MethodInfo possibleRoundMethod = FindStaticMethod(typeof(Decimal), "Round", typeof(decimal));

            if (possibleRoundMethod != null)
            {
                staticMethods.Add(possibleRoundMethod,
                                  new MemberInfoKey(typeof(Decimal), "Round", true, false, typeof(decimal)));
            }

            // Windows Phone 7.5 does not support Math.Floor(), Math.Round() and Math.Ceiling() for decimals
            MethodInfo possibleCeilingMethodMath = FindStaticMethod(typeof(Math), "Ceiling", typeof(decimal));

            if (possibleCeilingMethodMath != null)
            {
                staticMethods.Add(possibleCeilingMethodMath,
                                  new MemberInfoKey(typeof(Math), "Ceiling", true, false, typeof(decimal)));
            }

            MethodInfo possibleFloorMethodMath = FindStaticMethod(typeof(Math), "Floor", typeof(decimal));

            if (possibleFloorMethodMath != null)
            {
                staticMethods.Add(possibleFloorMethodMath,
                                  new MemberInfoKey(typeof(Math), "Floor", true, false, typeof(decimal)));
            }

            MethodInfo possibleRoundMethodMath = FindStaticMethod(typeof(Math), "Round", typeof(decimal));

            if (possibleRoundMethodMath != null)
            {
                staticMethods.Add(possibleRoundMethodMath,
                                  new MemberInfoKey(typeof(Math), "Round", true, false, typeof(decimal)));
            }

            foreach (MethodInfo key in staticMethods.Keys)
            {
                foreach (var pair in staticMethods)
                {
                    MemberInfoKey other = new MemberInfoKey(key);
                    if (key == pair.Key)
                    {
                        Assert.IsTrue(pair.Value.Equals(other));
                    }
                    else
                    {
                        Assert.IsFalse(pair.Value.Equals(other));
                    }
                }
            }
        }
        /// <summary>
        /// Process method calls and translate them into OData.
        /// </summary>
        /// <param name="expression">
        /// The expression to visit.
        /// </param>
        /// <returns>
        /// The visited expression.
        /// </returns>
        private Expression VisitMethodCall(MethodCallExpression expression)
        {
            // Look for either an instance or static method
            string methodName = null;
            MemberInfoKey methodInfoKey = new MemberInfoKey(expression.Method);
            if (InstanceMethods.TryGetValue(methodInfoKey, out methodName))
            {
                this.VisitODataMethodCall(expression, methodName, false);
            }
            else if (StaticMethods.TryGetValue(methodInfoKey, out methodName))
            {
                this.VisitODataMethodCall(expression, methodName, true);
            }
            else if (expression.Method.GetBaseDefinition().Equals(toStringMethod))
            {
                // handle the ToString method here
                // toString will only occur on expression that rely on a parameter,
                // because otherwise the partial evaluator would have already evaluated it
                // we get the base definition to detect overrides of ToString, which are pretty common
                this.Visit(expression.Object);
            }
            else
            {
                this.VisitCustomMethodCall(expression);
            }

            return expression;
        }
        /// <summary>
        /// Process member references.
        /// </summary>
        /// <param name="expression">
        /// The expression to visit.
        /// </param>
        /// <returns>
        /// The visited expression.
        /// </returns>
        private Expression VisitMemberAccess(MemberExpression expression)
        {
            // Lookup the Mobile Services name of the member and use that
            string memberName = GetTableMemberName(expression, this.contractResolver);
            if (memberName != null)
            {
                this.filter.Append(memberName);
                return expression;
            }
            
            // Check if this member is actually a function that looks like a
            // property (like string.Length, etc.)
            string methodName = null;
            MemberInfoKey memberInfoKey = new MemberInfoKey(expression.Member);
            if (InstanceProperties.TryGetValue(memberInfoKey, out methodName))
            {
                this.filter.Append(methodName);
                this.filter.Append("(");
                this.Visit(expression.Expression);
                this.filter.Append(")");
                return expression;
            }

            // Otherwise we can't process the member.
            throw new NotSupportedException(
                string.Format(
                    CultureInfo.InvariantCulture,
                    Resources.FilterBuildingExpressionVisitor_MemberUnsupported,
                    expression != null && expression.Member != null ? expression.Member.Name : null,
                    expression != null ? expression.ToString() : null));
        }
        public void CorrectlyMatchesInstanceMemberInfos()
        {
            Dictionary<MethodInfo, MemberInfoKey> instanceMethods =
                new Dictionary<MethodInfo, MemberInfoKey>() {
                { FindInstanceMethod(typeof(string), "ToLower"), 
                    new MemberInfoKey(typeof(string), "ToLower", true, true) },
                { FindInstanceMethod(typeof(string), "ToLowerInvariant"),
                    new MemberInfoKey(typeof(string), "ToLowerInvariant", true, true) },
                { FindInstanceMethod(typeof(string), "ToUpper"),
                    new MemberInfoKey(typeof(string), "ToUpper", true, true) },
                { FindInstanceMethod(typeof(string), "ToUpperInvariant"),
                    new MemberInfoKey(typeof(string), "ToUpperInvariant", true, true) },
                { FindInstanceMethod(typeof(string), "Trim"),
                    new MemberInfoKey(typeof(string), "Trim", true, true) },
                { FindInstanceMethod(typeof(string), "StartsWith", typeof(string)),
                    new MemberInfoKey(typeof(string), "StartsWith", true, true, typeof(string)) },
                { FindInstanceMethod(typeof(string), "EndsWith", typeof(string)),
                    new MemberInfoKey(typeof(string), "EndsWith", true, true, typeof(string)) },
                { FindInstanceMethod(typeof(string), "IndexOf", typeof(string)),
                    new MemberInfoKey(typeof(string), "IndexOf", true, true, typeof(string)) },
                { FindInstanceMethod(typeof(string), "IndexOf", typeof(char)),
                    new MemberInfoKey(typeof(string), "IndexOf", true, true, typeof(char)) },
                { FindInstanceMethod(typeof(string), "Contains", typeof(string)),
                    new MemberInfoKey(typeof(string), "Contains", true, true, typeof(string)) },
                { FindInstanceMethod(typeof(string), "Replace", typeof(string), typeof(string)),
                    new MemberInfoKey(typeof(string), "Replace", true, true, typeof(string), typeof(string)) },
                { FindInstanceMethod(typeof(string), "Replace", typeof(char), typeof(char)),
                    new MemberInfoKey(typeof(string), "Replace", true, true, typeof(char), typeof(char)) },
                { FindInstanceMethod(typeof(string), "Substring", typeof(int)),
                    new MemberInfoKey(typeof(string), "Substring", true, true, typeof(int)) },
                { FindInstanceMethod(typeof(string), "Substring", typeof(int), typeof(int)),
                    new MemberInfoKey(typeof(string), "Substring", true, true, typeof(int), typeof(int)) },
            };

            foreach (MethodInfo key in instanceMethods.Keys)
            {
                foreach (var pair in instanceMethods)
                {
                    MemberInfoKey other = new MemberInfoKey(key);
                    if (key == pair.Key)
                    {
                        Assert.IsTrue(pair.Value.Equals(other));
                    }
                    else
                    {
                        Assert.IsFalse(pair.Value.Equals(other));
                    }
                }
            }
        }
        public void CorrectlyMatchesPropertyInfos()
        {
            Dictionary<MemberInfo, MemberInfoKey> instanceProperties =
                new Dictionary<MemberInfo, MemberInfoKey>() {
                 { FindInstanceProperty(typeof(string), "Length"), 
                     new MemberInfoKey(typeof(string), "Length", false, true) },
                 { FindInstanceProperty(typeof(DateTime), "Day"), 
                     new MemberInfoKey(typeof(DateTime), "Day", false, true) },
                 { FindInstanceProperty(typeof(DateTime), "Month"), 
                     new MemberInfoKey(typeof(DateTime), "Month", false, true) },
                 { FindInstanceProperty(typeof(DateTime), "Year"),
                     new MemberInfoKey(typeof(DateTime), "Year", false, true) },
                 { FindInstanceProperty(typeof(DateTime), "Hour"), 
                     new MemberInfoKey(typeof(DateTime), "Hour", false, true) },
                 { FindInstanceProperty(typeof(DateTime), "Minute"), 
                     new MemberInfoKey(typeof(DateTime), "Minute", false, true) },
                 { FindInstanceProperty(typeof(DateTime), "Second"),
                     new MemberInfoKey(typeof(DateTime), "Second", false, true) },
            };

            foreach (MemberInfo key in instanceProperties.Keys)
            {
                foreach (var pair in instanceProperties)
                {
                    MemberInfoKey other = new MemberInfoKey(key);
                    if (key == pair.Key)
                    {
                        Assert.IsTrue(pair.Value.Equals(other));
                    }
                    else
                    {
                        Assert.IsFalse(pair.Value.Equals(other));
                    }
                }
            }
        }
        public void CorrectlyMatchesStaticMemberInfos()
        {
            Dictionary<MethodInfo, MemberInfoKey> staticMethods =
                new Dictionary<MethodInfo, MemberInfoKey>
            {
                { FindStaticMethod(typeof(Math), "Floor", typeof(double)), 
                    new MemberInfoKey(typeof(Math), "Floor", true, false, typeof(double)) },                 
                { FindStaticMethod(typeof(Math), "Ceiling", typeof(double)), 
                    new MemberInfoKey(typeof(Math), "Ceiling", true, false, typeof(double)) },  
                { FindStaticMethod(typeof(Math), "Round", typeof(double)), 
                    new MemberInfoKey(typeof(Math), "Round", true, false, typeof(double)) },
                { FindStaticMethod(typeof(string), "Concat", typeof(string), typeof(string)), 
                    new MemberInfoKey(typeof(string), "Concat", true, false, typeof(string), typeof(string)) }
            };

            // Windows 8 supports decimal.Floor(), decimal.Ceiling() and decimal.Round(), but Windows Phone does not, 
            // so we have to ensure these method infos exist before we add them.
            MethodInfo possibleFloorMethod = FindStaticMethod(typeof(Decimal), "Floor", typeof(decimal));
            if (possibleFloorMethod != null)
            {
                staticMethods.Add(possibleFloorMethod,
                    new MemberInfoKey(typeof(Decimal), "Floor", true, false, typeof(decimal)));
            }

            MethodInfo possibleCeilingMethod = FindStaticMethod(typeof(Decimal), "Ceiling", typeof(decimal));
            if (possibleCeilingMethod != null)
            {
                staticMethods.Add(possibleCeilingMethod,
                    new MemberInfoKey(typeof(Decimal), "Ceiling", true, false, typeof(decimal)));
            }

            MethodInfo possibleRoundMethod = FindStaticMethod(typeof(Decimal), "Round", typeof(decimal));
            if (possibleRoundMethod != null)
            {
                staticMethods.Add(possibleRoundMethod,
                    new MemberInfoKey(typeof(Decimal), "Round", true, false, typeof(decimal)));
            }

            // Windows Phone 7.5 does not support Math.Floor(), Math.Round() and Math.Ceiling() for decimals 
            MethodInfo possibleCeilingMethodMath = FindStaticMethod(typeof(Math), "Ceiling", typeof(decimal));
            if (possibleCeilingMethodMath != null)
            {
                staticMethods.Add(possibleCeilingMethodMath,
                    new MemberInfoKey(typeof(Math), "Ceiling", true, false, typeof(decimal)));
            }

            MethodInfo possibleFloorMethodMath = FindStaticMethod(typeof(Math), "Floor", typeof(decimal));
            if (possibleFloorMethodMath != null)
            {
                staticMethods.Add(possibleFloorMethodMath,
                    new MemberInfoKey(typeof(Math), "Floor", true, false, typeof(decimal)));
            }

            MethodInfo possibleRoundMethodMath = FindStaticMethod(typeof(Math), "Round", typeof(decimal));
            if (possibleRoundMethodMath != null)
            {
                staticMethods.Add(possibleRoundMethodMath,
                    new MemberInfoKey(typeof(Math), "Round", true, false, typeof(decimal)));
            }

            foreach (MethodInfo key in staticMethods.Keys)
            {
                foreach (var pair in staticMethods)
                {
                    MemberInfoKey other = new MemberInfoKey(key);
                    if (key == pair.Key)
                    {
                        Assert.IsTrue(pair.Value.Equals(other));
                    }
                    else
                    {
                        Assert.IsFalse(pair.Value.Equals(other));
                    }
                }
            }
        }
        /// <summary>
        /// Process member references.
        /// </summary>
        /// <param name="expression">
        /// The expression to visit.
        /// </param>
        /// <returns>
        /// The visited expression.
        /// </returns>
        private Expression VisitMemberAccess(MemberExpression expression)
        {
            // Lookup the Mobile Services name of the member and use that
            string memberName = GetTableMemberName(expression, this.contractResolver);
            if (memberName != null)
            {
                this.filterExpression.Push(new MemberAccessNode(null, memberName));
                return expression;
            }
            
            // Check if this member is actually a function that looks like a
            // property (like string.Length, etc.)
            string methodName = null;
            MemberInfoKey memberInfoKey = new MemberInfoKey(expression.Member);
            if (InstanceProperties.TryGetValue(memberInfoKey, out methodName))
            {
                var fnCallNode = new FunctionCallNode(methodName, null);
                this.filterExpression.Push(fnCallNode);

                this.Visit(expression.Expression);

                this.SetChildren(fnCallNode);

                return expression;
            }

            // Otherwise we can't process the member.
            throw new NotSupportedException(
                string.Format(
                    CultureInfo.InvariantCulture,
                    "The member '{0}' is not supported in the 'Where' Mobile Services query expression '{1}'.",
                    expression != null && expression.Member != null ? expression.Member.Name : null,
                    expression != null ? expression.ToString() : null));
        }