예제 #1
0
        // 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);
            }
        }