/// <summary>
        /// Gets the value of an open property
        /// </summary>
        /// <param name="value">The instance to get the property value from</param>
        /// <param name="propertyName">The open property name</param>
        /// <returns>The open property's value</returns>
        public virtual object GetValue(object value, string propertyName)
        {
            ExceptionUtilities.CheckArgumentNotNull(value, "value");
            ExceptionUtilities.CheckArgumentNotNull(propertyName, "propertyName");

            // for sub-values of a complex type inside an open property, GetValue will still be used
            // so we should check before calling GetOpenPropertyValue (which will throw on non-open types)
            ResourceType type = this.GetResourceType(value);

            ExceptionUtilities.CheckObjectNotNull(type, "GetValue called with object of unknown type. Type was '{0}'", value.GetType());
            if (type.IsOpenType)
            {
                return(this.QueryProvider.GetOpenPropertyValue(value, propertyName));
            }

            ExceptionUtilities.Assert(type.ResourceTypeKind == ResourceTypeKind.ComplexType, "OpenTypeMethods.GetValue used on non-open, non-complex type '{0}'", type.FullName);
            ResourceProperty resourceProperty = type.GetAllPropertiesLazily().SingleOrDefault(p => p.Name == propertyName);

            ExceptionUtilities.CheckObjectNotNull(resourceProperty, "OpenTypeMethods.GetValue used on non-open type '{0}' with non-existent property '{1}'", type.FullName, propertyName);

            return(this.QueryProvider.GetPropertyValue(value, resourceProperty));
        }
        /// <summary>
        /// Tries to get a replacement expression for the given method with the given parameters
        /// </summary>
        /// <param name="toReplace">The method to replace</param>
        /// <param name="parameters">The parameters to the method</param>
        /// <param name="replaced">The replaced expression</param>
        /// <returns>True if a replacement was made, false otherwise</returns>
        public override bool TryGetReplacement(MethodInfo toReplace, IEnumerable <Expression> parameters, out Expression replaced)
        {
            if (this.CanReplace(toReplace) && toReplace.Name == "OfType")
            {
                var parameterExpressions = parameters.ToList();
                ExceptionUtilities.Assert(parameterExpressions.Count == 2, "OfType requires exactly 2 parameter expressions");

                var constantExpression = parameterExpressions[1] as ConstantExpression;
                ExceptionUtilities.CheckObjectNotNull(constantExpression, "OfType requires the 2nd parameter to be a constant");

                var resourceType = constantExpression.Value as ResourceType;
                ExceptionUtilities.CheckObjectNotNull(constantExpression, "OfType requires the 2nd parameter to be a resource type");

                var genericArguments = toReplace.GetGenericArguments();
                ExceptionUtilities.Assert(genericArguments.Length == 2, "OfType requires exactly 2 generic arguments");

                replaced = this.OfType(parameterExpressions[0], resourceType, genericArguments[0], genericArguments[1]);
                return(true);
            }

            return(base.TryGetReplacement(toReplace, parameters, out replaced));
        }