代码之家  ›  专栏  ›  技术社区  ›  User1551892

为什么字典属性设置器在字典中添加新项时不执行?

  •  0
  • User1551892  · 技术社区  · 6 年前

    我有一节课 Wrapper 它有字典属性 DictA 我想在字典中添加一个新项时序列化类的实例。但是当我在 口述 ,和 口述 属性设置器不执行。我想,我遗漏了字典的一些基本行为,我需要帮助来理解它。下面是我正在使用的示例代码。。。

    public class Product 
    {
        public string Name     { get; set; }
        public DateTime Expiry { get; set; }
        public string[ ] Sizes { get; set; }
    }
    
    public class Wrapper : INotifyPropertyChanged 
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private Dictionary<string, Product> dictA_;    
        public Wrapper() => dictA_ = new Dictionary<string, Product>();
    
        public Dictionary<string, Product> DictA 
        {
            get => dictA_;
            set 
            {
                dictA_ = value;
                SerializeToJson();  // trying to serialize in simple fashion without event handling           
            }
        }
    
        public void SerializeToJson() 
        {
            string path = @"..\JsonTest.json";  // path
            string json = JsonConvert.SerializeObject( this );
            JsonSerializer serializer = new JsonSerializer( );
    
            using(StreamWriter sw = new StreamWriter(path)) 
            {
                using(JsonWriter writer = new JsonTextWriter(sw)) 
                {
                    serializer.Serialize( writer, this );
                }
            }
        }
    }
    
    public static void Main(string[] args) 
    {
        var product    = new Product();
        product.Name   = "Apple";
        product.Expiry = new DateTime(2008, 12, 28);
        product.Sizes  = new string[] {"Small"};
    
        var temp = new Wrapper();
        temp.DictA.Add("test", product);
        Thread.Sleep(1000 * 15);
    
        temp.DictA.Add("test2", product);
        Thread.Sleep(1000 * 15);
    
        temp.DictA.Add("test3", product);
        Console.ReadKey();
    }
    
    3 回复  |  直到 6 年前
        1
  •  1
  •   Dan Scott    6 年前

    正如评论所说,您要添加到集合,而不是设置集合值,一个好的解决方案是创建自定义类并从字典继承,这样做可以解决您的问题:

    class SerialisableDictionary<TKey, TValue> : Dictionary<TKey, TValue>
    {
        public new void Add(TKey key, TValue value)
        {
            base.Add(key, value);
            SerializeToJson();
        }
    }
    
        2
  •  3
  •   Owen Pauling tmatuschek    6 年前

    setter只用于将对字典的引用分配给该属性。它与向属性引用的任何字典中添加值无关。

    如果希望在向字典添加新值时发生某些逻辑,则应编写自己的类实现 IDictionary<TKey, TValue> . 使用现有的 Dictionary<TKey, TValue> 实现来支持它,但在 Add 方法实现,然后将值添加到字典中。

        3
  •  0
  •   User1551892    6 年前

    最后,我终于找到了我正在寻找的解决方案。请回顾,如果有错误,请突出显示:

    public class Product {
    
        public string Name { get; set; }
    
        public DateTime Expiry { get; set; }
    
        public string[ ] Sizes { get; set; }
    
      }
    
      public class DictionaryWithJsonSerailization<TKey, TValue> : IDictionary<TKey, TValue>, INotifyPropertyChanged {
    
        #region Events
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        #endregion
    
        #region Private fields
    
    
        Dictionary<TKey, TValue> _interalDictionary;
    
        #endregion
    
        #region Constructor
    
        public DictionaryWithJsonSerailization( ) {
          _interalDictionary = new Dictionary<TKey, TValue>( );
        }
    
    
    
    
        #endregion
    
        #region implementation of IDictionary<TKey, TValue> interface
    
    
    
        public TValue this[ TKey key ] {
          get {
            try {
              return ( TValue )_interalDictionary[ key ];
            }
            catch( Exception ex ) {
              return default( TValue );
            }
          }
    
          set {
            _interalDictionary[ key ] = value;
            NotifyObserversOfChange( );
          }
        }
    
        public ICollection<TKey> Keys {
          get {
            return _interalDictionary.Select( x => ( TKey )x.Key ).ToList( );
          }
        }
    
        public ICollection<TValue> Values {
          get {
            return _interalDictionary.Select( x => ( TValue )x.Value ).ToList( );
          }
        }
    
        public int Count {
          get {
            return _interalDictionary.Count;
          }
        }
    
        public bool IsReadOnly {
          get {
            return false;
          }
        }
    
        public void Add( TKey key, TValue value ) {
          _interalDictionary.Add( key, value );
          NotifyObserversOfChange( );
        }
    
        public void Add( KeyValuePair<TKey, TValue> item ) {
          _interalDictionary.Add( item.Key, item.Value );
          NotifyObserversOfChange( );
        }
    
        public void Clear( ) {
          _interalDictionary = new Dictionary<TKey, TValue>( );
          NotifyObserversOfChange( );
        }
    
        public bool Contains( KeyValuePair<TKey, TValue> item ) {
    
          return _interalDictionary.Contains( item );
        }
    
        public bool ContainsKey( TKey key ) {
    
          return _interalDictionary.ContainsKey( key );
        }
    
        public void CopyTo( KeyValuePair<TKey, TValue>[ ] array, int arrayIndex ) {
          throw new NotImplementedException( );
        }
    
        public bool Remove( TKey key ) {
          try {
            _interalDictionary.Remove( key );
            NotifyObserversOfChange( );
            return true;
          }
          catch( Exception ex ) {
            return false;
          }
    
        }
    
        public bool Remove( KeyValuePair<TKey, TValue> item ) {
          try {
            _interalDictionary.Remove( item.Key );
            NotifyObserversOfChange( );
            return true;
          }
          catch( Exception ex ) {
            return false;
          }
        }
    
        public bool TryGetValue( TKey key, out TValue value ) {
          try {
            value = ( TValue )_interalDictionary[ key ];
            return true;
          }
          catch( Exception ex ) {
            value = default( TValue );
            return false;
          }
        }
    
        IEnumerator IEnumerable.GetEnumerator( ) {
          return ( ( IDictionary<TKey, TValue> )this ).GetEnumerator( );
        }
    
        IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator( ) {
          return _interalDictionary.GetEnumerator( );
        }
    
        #endregion
    
        #region Private methods
    
        private void NotifyObserversOfChange( ) {
          var propertyHandler = PropertyChanged;
          if( propertyHandler != null ) {
            if( propertyHandler != null ) {
              propertyHandler( this, new PropertyChangedEventArgs( "Count" ) );
              propertyHandler( this, new PropertyChangedEventArgs( "Keys" ) );
              propertyHandler( this, new PropertyChangedEventArgs( "Values" ) );
              propertyHandler( this, new PropertyChangedEventArgs( "this" ) );
            }
          }
        }
    
        public IEnumerator GetEnumerator( ) {
          throw new NotImplementedException( );
        }
    
        #endregion
    
    
      }
    
      public class Wrapper {
    
        DictionaryWithJsonSerailization<string, Product> dictA_;
    
        public Wrapper( ) {
          dictA_ = new DictionaryWithJsonSerailization<string, Product>( );
          dictA_.PropertyChanged += ( sener, i ) => SerializeToJson( );
    
    
        }
    
        public DictionaryWithJsonSerailization<string, Product> DictA {
          get {
            return dictA_;
          }
          set {
            dictA_ = value;
          }
        }
    
        public void SerializeToJson( ) {
          string path = @"...\JsonTest.json";
          string json = JsonConvert.SerializeObject( this );
          JsonSerializer serializer = new JsonSerializer( );
    
          using( StreamWriter sw = new StreamWriter( path ) ) {
            using( JsonWriter writer = new JsonTextWriter( sw ) ) {
              serializer.Serialize( writer, this );
            }
          }
        }
    
      }
    
    static void Main( string[ ] args ) {
    
    
        Product product = new Product( );
        product.Name = "Apple";
        product.Expiry = new DateTime( 2008, 12, 28 );
        product.Sizes = new string[ ] { "Small" };
    
        var temp = new Wrapper( );
        temp.DictA.Add( "test", product );
        Thread.Sleep( 1000 * 15 );
        temp.DictA.Add( "test2", product );
        Thread.Sleep( 1000 * 15 );
        temp.DictA.Add( "test3", product );
      }
    

    我正试图在dictionary中添加一些延迟后的项,每当dictionary中添加新项时,拥有该dictionary的对象都存储在计算机驱动器上的json文件中。