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