/// <summary>
        /// Generates a untyped function to allow retrieving property values for instances of the specified type without using reflection.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        public static Func <object, object> CreatePropertyValueGetter(Type type, string propertyName)
        {
            if (type == null)
            {
                throw new ArgumentException("type argument is NULL.");
            }

            if (propertyName == null)
            {
                throw new ArgumentException("propertyName argument is NULL.");
            }

            TypeInfo info = type.GetTypeInfo();

            if (info.IsNotPublic)
            {
                throw new ArgumentException("Cannot create dynamic property getter for non-public types.");
            }

            if (info.IsValueType)
            {
                throw new ArgumentException("Dynamic getter is not supported for value type [" + info.Name + "]");
            }

            return(BindingExpressionHelper.CreateGetValueFunc(type, propertyName));
        }
        /// <summary>
        /// Returns a function that will return the value of the property, specified by the provided propertyPath.
        /// </summary>
        /// <param name="itemType">The type of the instance which property will be returned.</param>
        /// <param name="propertyPath">The path of the property which value will be returned.</param>
        public static Func <object, object> CreateGetValueFunc(Type itemType, string propertyPath)
        {
            // Strange problem in Design Mode - Missing method exceptions are thrown when we try to compile the lambda below.
            if (!itemType.GetTypeInfo().IsPublic || DesignMode.DesignModeEnabled ||
                (propertyPath != null && propertyPath.IndexOfAny(new char[] { '.', '[', ']', '(', ')', '@' }) > -1))
            {
                return((item) => BindingExpressionHelper.GetValueThroughBinding(item, propertyPath));
            }

#if WINDOWS_UWP
            PropertyInfo propertyInfo = itemType.GetRuntimeProperty(propertyPath);
            return(item => propertyInfo.GetValue(item));
#else
            var parameter = Expression.Parameter(itemType, "item");

            Expression getter;
            if (string.IsNullOrEmpty(propertyPath))
            {
                getter = parameter;
            }
            else
            {
                getter = Expression.PropertyOrField(parameter, propertyPath);
            }

            var lambda   = Expression.Lambda(getter, parameter);
            var compiled = lambda.Compile();

            var methodInfo = typeof(BindingExpressionHelper).GetTypeInfo()
                             .GetDeclaredMethod("ToUntypedFunc")
                             .MakeGenericMethod(new[] { itemType, lambda.Body.Type });

            return((Func <object, object>)methodInfo.Invoke(null, new object[] { compiled }));
#endif
        }
        private static object GetValueThroughBinding(object item, Binding binding)
        {
            BindingExpressionHelper helper = new BindingExpressionHelper();

            try
            {
                helper.DataContext = item;
                BindingOperations.SetBinding(helper, ValueProperty, binding);
                return(helper.GetValue(ValueProperty));
            }
            finally
            {
                helper.ClearValue(BindingExpressionHelper.ValueProperty);
            }
        }