csharp 可观察字典结构模型

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了csharp 可观察字典结构模型相关的知识,希望对你有一定的参考价值。

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq.Expressions;

namespace Common
{
    public class ViewModelBase : INotifyPropertyChanged, IExtendableViewModel
    {
        private readonly IDictionary<string, object> _values = new Dictionary<string, object>();

        public event PropertyChangedEventHandler PropertyChanged;

        public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
        {
            return _values.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        public void Extend(IEnumerable<KeyValuePair<string, object>> pairs)
        {
            foreach (var pair in pairs)
                Set(pair.Key, pair.Value);
        }

        protected T Get<T>(Expression<Func<T>> expression)
        {
            return Get(PropertyName(expression), default(T));
        }

        private T Get<T>(string name, T defaultValue)
        {
            if (_values.ContainsKey(name))
            {
                return (T)_values[name];
            }

            return defaultValue;
        }

        protected void Set<T>(Expression<Func<T>> expression, T value)
        {
            Set(PropertyName(expression), value);
        }

        private void Set<T>(string name, T value)
        {
            if (_values.ContainsKey(name))
            {
                var target = _values[name];
                if (target == null && ((!typeof(T).IsPrimitive && value == null) || value.Equals(default(T))))
                    return;

                if (target != null && target.Equals(value))
                    return;

                _values[name] = value;
            }
            else
            {
                _values.Add(name, value);
            }

            OnPropertyChanged(name);
        }

        protected string PropertyName<T>(Expression<Func<T>> expression)
        {
            var memberExpression = expression.Body as MemberExpression;

            if (memberExpression == null)
                throw new ArgumentException("expression must be a property expression");

            return memberExpression.Member.Name;
        }

        protected void OnPropertyChanged(string propertyName)
        {
            this.SyncNotify(propertyName, PropertyChanged);
        }

        protected void OnPropertyChanged<T>(Expression<Func<T>> expression)
        {
            OnPropertyChanged(PropertyName(expression));
        }
    }
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;

namespace Common
{
    public class ObservableDictionary<TKey, TValue> : ViewModelBase, IDictionary<TKey, TValue>, INotifyCollectionChanged
    {
        protected IDictionary<TKey, TValue> Dictionary { get; private set; }

        public ObservableDictionary()
        {
            Dictionary = new Dictionary<TKey, TValue>();
        }

        public ObservableDictionary(IDictionary<TKey, TValue> dictionary)
        {
            Dictionary = new Dictionary<TKey, TValue>(dictionary);
        }

        public ObservableDictionary(IEqualityComparer<TKey> comparer)
        {
            Dictionary = new Dictionary<TKey, TValue>(comparer);
        }

        public ObservableDictionary(int capacity)
        {
            Dictionary = new Dictionary<TKey, TValue>(capacity);
        }

        public ObservableDictionary(IDictionary<TKey, TValue> dictionary, IEqualityComparer<TKey> comparer)
        {
            Dictionary = new Dictionary<TKey, TValue>(dictionary, comparer);
        }

        public ObservableDictionary(int capacity, IEqualityComparer<TKey> comparer)
        {
            Dictionary = new Dictionary<TKey, TValue>(capacity, comparer);
        }

        #region IDictionary<TKey,TValue> Members

        public void Add(TKey key, TValue value)
        {
            Update(key, value, true);
        }

        public bool ContainsKey(TKey key)
        {
            return Dictionary.ContainsKey(key);
        }

        ICollection<TKey> IDictionary<TKey, TValue>.Keys
        {
            get { return Dictionary.Keys; }
        }

        public bool Remove(TKey key)
        {
            if (key == null) throw new ArgumentNullException("key");

            if (!Dictionary.ContainsKey(key))
                throw new ArgumentException("Invalid key", "key");

            var removed = Dictionary.Remove(key);

            var value = Dictionary[key];
            if (removed)
                OnCollectionChanged(
                    NotifyCollectionChangedAction.Remove, new KeyValuePair<TKey, TValue>(key, value));

            return removed;
        }

        bool IDictionary<TKey, TValue>.TryGetValue(TKey key, out TValue value)
        {
            return Dictionary.TryGetValue(key, out value);
        }

        ICollection<TValue> IDictionary<TKey, TValue>.Values
        {
            get { return Dictionary.Values; }
        }

        public TValue this[TKey key]
        {
            get { return Dictionary[key]; }
            set { Update(key, value, false); }
        }

        #endregion

        #region ICollection<KeyValuePair<TKey,TValue>> Members

        void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
        {
            Update(item.Key, item.Value, true);
        }

        void ICollection<KeyValuePair<TKey, TValue>>.Clear()
        {
            if (Dictionary.Count <= 0) return;

            Dictionary.Clear();

            OnCollectionChanged(NotifyCollectionChangedAction.Reset);
        }

        bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
        {
            return Dictionary.Contains(item);
        }

        void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
        {
            Dictionary.CopyTo(array, arrayIndex);
        }

        int ICollection<KeyValuePair<TKey, TValue>>.Count
        {
            get { return Dictionary.Count; }
        }

        bool ICollection<KeyValuePair<TKey, TValue>>.IsReadOnly
        {
            get { return Dictionary.IsReadOnly; }
        }

        public bool Remove(KeyValuePair<TKey, TValue> item)
        {
            return Remove(item.Key);
        }

        #endregion

        IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
        {
            return Dictionary.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return ((IEnumerable)Dictionary).GetEnumerator();
        }

        public event NotifyCollectionChangedEventHandler CollectionChanged;

        public void AddRange(IDictionary<TKey, TValue> items)
        {
            if (items == null) throw new ArgumentNullException("items");

            if (items.Count <= 0) return;

            if (items.Keys.Any(key => Dictionary.ContainsKey(key)))
                throw new ArgumentException("An item with the same key has already been added.");

            foreach (var item in items) Dictionary.Add(item);

            OnCollectionChanged(NotifyCollectionChangedAction.Add, items.ToArray());
        }

        private void Update(TKey key, TValue value, bool add)
        {
            if (key == null) throw new ArgumentNullException("key");

            TValue item;
            if (!Dictionary.TryGetValue(key, out item))
            {
                Dictionary[key] = value;

                OnCollectionChanged(NotifyCollectionChangedAction.Add, new KeyValuePair<TKey, TValue>(key, value));

                return;
            }

            if (add) throw new ArgumentException("An item with the same key has already been added.");

            if (Equals(item, value)) return;

            Dictionary[key] = value;

            OnCollectionChanged(NotifyCollectionChangedAction.Replace, new KeyValuePair<TKey, TValue>(key, value), new KeyValuePair<TKey, TValue>(key, item));
        }

        private void OnPropertyChanged()
        {
            OnPropertyChanged(PropertyName(() => Dictionary.Count));
            OnPropertyChanged(PropertyName(() => Dictionary.Keys));
            OnPropertyChanged(PropertyName(() => Dictionary.Values));
        }

        private void OnCollectionChanged(NotifyCollectionChangedAction action)
        {
            OnPropertyChanged();
            if (CollectionChanged != null)
                CollectionChanged(this, new NotifyCollectionChangedEventArgs(action));
        }

        private void OnCollectionChanged(NotifyCollectionChangedAction action, KeyValuePair<TKey, TValue> changedItem)
        {
            OnPropertyChanged();
            if (CollectionChanged != null)
                CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, changedItem));
        }

        private void OnCollectionChanged(NotifyCollectionChangedAction action, KeyValuePair<TKey, TValue> newItem, KeyValuePair<TKey, TValue> oldItem)
        {
            OnPropertyChanged();
            if (CollectionChanged != null)
                CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, newItem, oldItem));
        }

        private void OnCollectionChanged(NotifyCollectionChangedAction action, IList newItems)
        {
            OnPropertyChanged();
            if (CollectionChanged != null)
                CollectionChanged(this, new NotifyCollectionChangedEventArgs(action, newItems));
        }
    }
}
using System.ComponentModel;
using System.Threading;
using System.Windows.Threading;

namespace Common
{
    public static class NotifyPropertyChangedExtensions
    {
        public static void SyncNotify(this INotifyPropertyChanged host, string propertyName, PropertyChangedEventHandler eventRaiser, bool wait = false, Dispatcher dispatcher = null)
        {
            dispatcher = dispatcher ?? Dispatcher.CurrentDispatcher;

            var args = new PropertyChangedEventArgs(propertyName);

            if (eventRaiser == null) return;

            if (dispatcher.Thread == Thread.CurrentThread)
            {
                eventRaiser(host, args);
                return;
            }

            if (wait)
            {
                dispatcher.Invoke(eventRaiser, host, args);
                return;
            }

            dispatcher.BeginInvoke(eventRaiser, host, args);
        }
    }
}
using System.Collections.Generic;

namespace Common
{
    public interface IExtendableViewModel<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
    {
        void Extend(IEnumerable<KeyValuePair<TKey, TValue>> pairs);
    }

    public interface IExtendableViewModel : IExtendableViewModel<string, object> { }
}

以上是关于csharp 可观察字典结构模型的主要内容,如果未能解决你的问题,请参考以下文章

csharp 用于处理.net模型状态的可重用ValidationFilter属性

4. 基本数据结构-字典

可观察对象模型在模型更新时不会更改视图值

观察 Swift 结构体的变化

DS301读书笔记

python-字典z