// ApplyCore is as slim as it should be: // Setting 100000 values : 17ms. // ApplyCore 100000 (w/o INPC, w/o unnapply) : 20ms. internal void ApplyCore(object sourceObject, BindableObject target, BindableProperty property, bool fromTarget = false) { var isTSource = sourceObject != null && sourceObject is TSource; var mode = this.GetRealizedMode(property); if ((mode == BindingMode.OneWay || mode == BindingMode.OneTime) && fromTarget) { return; } var needsGetter = (mode == BindingMode.TwoWay && !fromTarget) || mode == BindingMode.OneWay || mode == BindingMode.OneTime; if (isTSource && (mode == BindingMode.OneWay || mode == BindingMode.TwoWay) && proxyHandlers != null) { Subscribe((TSource)sourceObject); } if (needsGetter) { var value = property.DefaultValue; if (isTSource) { try { value = GetSourceValue(getter((TSource)sourceObject), property.ReturnType); } catch (Exception ex) when(ex is NullReferenceException || ex is KeyNotFoundException) { } } if (!TryConvert(ref value, property, property.ReturnType, true)) { // Log.Warning("Binding", "{0} can not be converted to type '{1}'", value, property.ReturnType); return; } target.SetValueCore(property, value, SetValueFlags.ClearDynamicResource, BindableObject.SetValuePrivateFlags.Default | BindableObject.SetValuePrivateFlags.Converted, false); return; } var needsSetter = (mode == BindingMode.TwoWay && fromTarget) || mode == BindingMode.OneWayToSource; if (needsSetter && setter != null && isTSource) { var value = GetTargetValue(target.GetValue(property), typeof(TProperty)); if (!TryConvert(ref value, property, typeof(TProperty), false)) { // Log.Warning("Binding", "{0} can not be converted to type '{1}'", value, typeof(TProperty)); return; } setter((TSource)sourceObject, (TProperty)value); } }
private static void OnLocalEulerAnglesChanged(BindableObject sender, object oldValue, object newValue) { sender.SetValueCore(LocalRotationProperty, UnityEngine.Quaternion.Euler((UnityEngine.Vector3)newValue)); }
private static void SetValueFromRenderer(BindableObject bindable, BindableProperty property, object value) { bindable.SetValueCore(property, value); }
/// <summary> /// Applies the binding expression to a previously set source or target. /// </summary> void ApplyCore(object sourceObject, BindableObject target, BindableProperty property, bool fromTarget = false) { BindingMode mode = Binding.GetRealizedMode(_targetProperty); if (mode == BindingMode.OneWay && fromTarget) return; bool needsGetter = (mode == BindingMode.TwoWay && !fromTarget) || mode == BindingMode.OneWay; bool needsSetter = !needsGetter && ((mode == BindingMode.TwoWay && fromTarget) || mode == BindingMode.OneWayToSource); object current = sourceObject; object previous = null; BindingExpressionPart part = null; for (var i = 0; i < _parts.Count; i++) { part = _parts[i]; bool isLast = i + 1 == _parts.Count; if (!part.IsSelf && current != null) { // Allow the object instance itself to provide its own TypeInfo var reflectable = current as IReflectableType; TypeInfo currentType = reflectable != null ? reflectable.GetTypeInfo() : current.GetType().GetTypeInfo(); if (part.LastGetter == null || !part.LastGetter.DeclaringType.GetTypeInfo().IsAssignableFrom(currentType)) SetupPart(currentType, part); if (!isLast) part.TryGetValue(current, out current); } if (!part.IsSelf && current != null) { if ((needsGetter && part.LastGetter == null) || (needsSetter && part.NextPart == null && part.LastSetter == null)) { Log.Warning("Binding", PropertyNotFoundErrorMessage, part.Content, current, target.GetType(), property.PropertyName); break; } } if (mode == BindingMode.OneWay || mode == BindingMode.TwoWay) { var inpc = current as INotifyPropertyChanged; if (inpc != null && !ReferenceEquals(current, previous)) { // If we're reapplying, we don't want to double subscribe inpc.PropertyChanged -= part.ChangeHandler; inpc.PropertyChanged += part.ChangeHandler; } } previous = current; } Debug.Assert(part != null, "There should always be at least the self part in the expression."); if (needsGetter) { object value = property.DefaultValue; if (part.TryGetValue(current, out value) || part.IsSelf) { value = Binding.GetSourceValue(value, property.ReturnType); } else value = property.DefaultValue; if (!TryConvert(part, ref value, property.ReturnType, true)) { Log.Warning("Binding", "{0} can not be converted to type '{1}'", value, property.ReturnType); return; } target.SetValueCore(property, value, BindableObject.SetValueFlags.ClearDynamicResource, BindableObject.SetValuePrivateFlags.Default | BindableObject.SetValuePrivateFlags.Converted); } else if (needsSetter && part.LastSetter != null && current != null) { object value = Binding.GetTargetValue(target.GetValue(property), part.SetterType); if (!TryConvert(part, ref value, part.SetterType, false)) { Log.Warning("Binding", "{0} can not be converted to type '{1}'", value, part.SetterType); return; } object[] args; if (part.IsIndexer) { args = new object[part.Arguments.Length + 1]; part.Arguments.CopyTo(args, 0); args[args.Length - 1] = value; } else if (part.IsBindablePropertySetter) { args = new[] { part.BindablePropertyField, value }; } else { args = new[] { value }; } part.LastSetter.Invoke(current, args); } }