/// <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));
        }