internal static WeakReference GetNativeObjectWeakReference(NSObject nsObject)
        {
            var handle = nsObject.Handle;

            if (handle == IntPtr.Zero)
            {
                return(Empty.WeakReference);
            }
            lock (AttachedValueHolders)
            {
                AttachedValueHolder value;
                if (!AttachedValueHolders.TryGetValue(handle, out value))
                {
                    value = new AttachedValueHolder(nsObject);
                    AttachedValueHolders[handle] = value;
                }
                return(value.WeakReference);
            }
        }
        protected override LightDictionaryBase <string, object> GetOrAddAttachedDictionary(object item, bool addNew)
        {
            var model = item as NotifyPropertyChangedBase;

            if (model != null)
            {
                return(AttachedValueProviderDefault.GetOrAddAttachedValues(model, true));
            }
#if TOUCH
            var nsObject = item as NSObject;
            if (nsObject != null)
            {
                var handle = nsObject.Handle;
                if (handle == IntPtr.Zero)
                {
                    if (addNew)
                    {
                        Tracer.Error("The object {0} is disposed the attached values cannot be obtained", item.GetType());
                        return(new AttachedValueDictionary());
                    }
                    return(null);
                }
                AttachedValueHolder holder;
                lock (AttachedValueHolders)
                {
                    if (!AttachedValueHolders.TryGetValue(handle, out holder))
                    {
                        if (!addNew)
                        {
                            return(null);
                        }
                        holder = new AttachedValueHolder(nsObject);
                        AttachedValueHolders[handle] = holder;
                    }
                }
                return(holder.GetOrCreateDictionary());
            }
#elif !WINFORMS && !NET_STANDARD && !ANDROID && !TOUCH && !XAMARIN_FORMS
            //Synchronization is not necessary because accessing the DependencyObject is possible only from the main thread.
            var dependencyObject = item as DependencyObject;
            if (dependencyObject != null)
            {
                var dict = (AttachedValueDictionary)dependencyObject.GetValue(AttachedValueDictionaryProperty);
                if (dict == null && addNew)
                {
                    dict = new AttachedValueDictionary();
                    dependencyObject.SetValue(AttachedValueDictionaryProperty, dict);
                }
                return(dict);
            }
#elif XAMARIN_FORMS
            var bindableObject = item as BindableObject;
            if (bindableObject != null)
            {
                var dict = (AttachedValueDictionary)bindableObject.GetValue(AttachedValueDictionaryProperty);
                if (dict == null && addNew)
                {
                    lock (_internalDictionary)
                    {
                        dict = (AttachedValueDictionary)bindableObject.GetValue(AttachedValueDictionaryProperty);
                        if (dict == null)
                        {
                            dict = new AttachedValueDictionary();
                            bindableObject.SetValue(AttachedValueDictionaryProperty, dict);
                        }
                    }
                }
                return(dict);
            }
#elif ANDROID
            if (SetTagSupported)
            {
                var view = item as View;
                if (view.IsAlive())
                {
                    var dict = (AttachedValueDictionaryJava)view.GetTag(Resource.Id.AttachedProperties);
                    if (dict == null && addNew)
                    {
                        lock (_internalDictionary)
                        {
                            dict = (AttachedValueDictionaryJava)view.GetTag(Resource.Id.AttachedProperties);
                            if (dict == null)
                            {
                                dict = new AttachedValueDictionaryJava();
                                view.SetTag(Resource.Id.AttachedProperties, dict);
                            }
                        }
                    }
                    return(dict?.Dictionary);
                }
            }

            //.NET object (Preference) is garbage collected and all attached members too but Java object is still alive.
            //Save values to activity dictionary.
            var pref = item as Preference;
            if (pref.IsAlive() && pref.HasKey)
            {
                try
                {
                    var activityView = pref.Context as IActivityView;
                    if (activityView != null)
                    {
                        var    metadata = activityView.Mediator.Metadata;
                        var    key      = pref.Key + pref.GetType().FullName + pref.GetHashCode();
                        object v;
                        if (!metadata.TryGetValue(key, out v))
                        {
                            if (addNew)
                            {
                                v             = new AttachedValueDictionary();
                                metadata[key] = v;
                            }
                        }
                        return((LightDictionaryBase <string, object>)v);
                    }
                }
                catch
                {
                    ;
                }
            }
#endif
            if (addNew)
            {
                return(_internalDictionary.GetValue(item, CreateDictionaryDelegate));
            }
            AttachedValueDictionary value;
            _internalDictionary.TryGetValue(item, out value);
            return(value);
        }
        protected override LightDictionaryBase <string, object> GetOrAddAttachedDictionary(object item, bool addNew)
        {
            var handler = GetOrAddAttachedDictionaryHandler?.GetInvocationList();

            if (handler != null)
            {
                for (int i = 0; i < handler.Length; i++)
                {
                    var result = ((Func <object, bool, LightDictionaryBase <string, object> >)handler[i]).Invoke(item, addNew);
                    if (result != null)
                    {
                        return(result);
                    }
                }
            }
            var model = item as NotifyPropertyChangedBase;

            if (model != null)
            {
                return(GetOrAddAttachedValues(model, true));
            }
#if TOUCH
            var nsObject = item as NSObject;
            if (nsObject != null)
            {
                var handle = nsObject.Handle;
                if (handle == IntPtr.Zero)
                {
                    if (addNew)
                    {
                        Tracer.Error("The object {0} is disposed the attached values cannot be obtained", item.GetType());
                        return(new AttachedValueDictionary());
                    }
                    return(null);
                }
                AttachedValueHolder holder;
                lock (AttachedValueHolders)
                {
                    if (!AttachedValueHolders.TryGetValue(handle, out holder))
                    {
                        if (!addNew)
                        {
                            return(null);
                        }
                        holder = new AttachedValueHolder(nsObject);
                        AttachedValueHolders[handle] = holder;
                    }
                }
                return(holder.GetOrCreateDictionary());
            }
#elif WINDOWS_UWP || WPF || WINFORMS
            //Synchronization is not necessary because accessing the DependencyObject is possible only from the main thread.
            var dependencyObject = item as DependencyObject;
            if (dependencyObject != null)
            {
                var dict = (AttachedValueDictionary)dependencyObject.GetValue(AttachedValueDictionaryProperty);
                if (dict == null && addNew)
                {
                    dict = new AttachedValueDictionary();
                    dependencyObject.SetValue(AttachedValueDictionaryProperty, dict);
                }
                return(dict);
            }
#elif XAMARIN_FORMS
            var bindableObject = item as BindableObject;
            if (bindableObject != null)
            {
                var dict = (AttachedValueDictionary)bindableObject.GetValue(AttachedValueDictionaryProperty);
                if (dict == null && addNew)
                {
                    lock (_internalDictionary)
                    {
                        dict = (AttachedValueDictionary)bindableObject.GetValue(AttachedValueDictionaryProperty);
                        if (dict == null)
                        {
                            dict = new AttachedValueDictionary();
                            bindableObject.SetValue(AttachedValueDictionaryProperty, dict);
                        }
                    }
                }
                return(dict);
            }
#elif ANDROID
            if (SetTagSupported)
            {
                var view = item as View;
                if (view.IsAlive())
                {
                    var dict = (AttachedValueDictionaryJava)view.GetTag(Resource.Id.AttachedProperties);
                    if (dict == null && addNew)
                    {
                        lock (_internalDictionary)
                        {
                            dict = (AttachedValueDictionaryJava)view.GetTag(Resource.Id.AttachedProperties);
                            if (dict == null)
                            {
                                dict = new AttachedValueDictionaryJava();
                                view.SetTag(Resource.Id.AttachedProperties, dict);
                            }
                        }
                    }
                    return(dict?.Dictionary);
                }
            }
#endif
            if (addNew)
            {
                return(_internalDictionary.GetValue(item, CreateDictionaryDelegate));
            }
            AttachedValueDictionary value;
            _internalDictionary.TryGetValue(item, out value);
            return(value);
        }