// 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) && _handlers != null) { Subscribe((TSource)sourceObject); } if (needsGetter) { var value = FallbackValue ?? property.GetDefaultValue(target); if (isTSource) { try { value = GetSourceValue(_getter((TSource)sourceObject), property.ReturnType); } catch (Exception ex) when(ex is NullReferenceException || ex is KeyNotFoundException || ex is IndexOutOfRangeException) { } } if (!BindingExpression.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); return; } var needsSetter = (mode == BindingMode.TwoWay && fromTarget) || mode == BindingMode.OneWayToSource; if (needsSetter && _setter != null && isTSource) { var value = GetTargetValue(target.GetValue(property), typeof(TProperty)); if (!BindingExpression.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); } }