Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么在字典中添加新项时不执行字典属性设置器?_C#_Dictionary - Fatal编程技术网

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

C# 为什么在字典中添加新项时不执行字典属性设置器?,c#,dictionary,C#,Dictionary,我有一个类Wrapper,它有一个dictionary属性DictA,我想在dictionary中添加一个新项后立即序列化该类的实例。但是,当我在DictA中插入新项时,DictA属性设置器不会执行。我想,我遗漏了字典的一些基本行为,我需要帮助来理解它。下面是我正在使用的示例代码 public class Product { public string Name { get; set; } public DateTime Expiry { get; set; }

我有一个类
Wrapper
,它有一个dictionary属性
DictA
,我想在dictionary中添加一个新项后立即序列化该类的实例。但是,当我在
DictA
中插入新项时,
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();
}
公共类产品
{
公共字符串名称{get;set;}
公共日期时间到期{get;set;}
公共字符串[]大小{get;set;}
}
公共类包装器:INotifyPropertyChanged
{
公共事件属性更改事件处理程序属性更改;
私人词典;
public Wrapper()=>dictA_=新字典();
公共词典格言
{
get=>dictA;
设置
{
dictA=值;
SerializeToJson();//尝试以简单方式序列化而不进行事件处理
}
}
public-void-tojson()
{
字符串路径=@“.\JsonTest.json”;//路径
字符串json=JsonConvert.SerializeObject(this);
JsonSerializer serializer=新的JsonSerializer();
使用(StreamWriter sw=新StreamWriter(路径))
{
使用(JsonWriter=newjsontextwriter(sw))
{
serializer.Serialize(writer,this);
}
}
}
}
公共静态void Main(字符串[]args)
{
var product=新产品();
product.Name=“苹果”;
产品有效期=新的日期时间(2008年12月28日);
product.size=新字符串[]{“小”};
var temp=new Wrapper();
温度指令添加(“测试”,产品);
线程。睡眠(1000*15);
临时指令添加(“测试2”,产品);
线程。睡眠(1000*15);
临时指令添加(“测试3”,产品);
Console.ReadKey();
}

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


如果希望在向字典中添加新值时出现一些逻辑,那么应该编写自己的类来实现
IDictionary
。使用现有的
字典
实现来支持它,但在将值添加到字典中之前,请在
添加
方法实现中执行自己的逻辑。

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


如果希望在向字典中添加新值时出现一些逻辑,那么应该编写自己的类来实现
IDictionary
。使用现有的
字典
实现来支持它,但在将值添加到字典中之前,请在
添加
方法实现中执行您自己的逻辑。

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

class SerialisableDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
    public new void Add(TKey key, TValue value)
    {
        base.Add(key, value);
        SerializeToJson();
    }
}
class SerialisableDictionary:字典
{
公共新空添加(TKey key,TValue value)
{
添加(键、值);
序列化为json();
}
}

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

class SerialisableDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
    public new void Add(TKey key, TValue value)
    {
        base.Add(key, value);
        SerializeToJson();
    }
}
class SerialisableDictionary:字典
{
公共新空添加(TKey key,TValue value)
{
添加(键、值);
序列化为json();
}
}

最后,我设法找到了我正在寻找的解决方案。请检查,如果有错误,请突出显示:

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 );
  }
公共类产品{
公共字符串名称{get;set;}
公共日期时间到期{get;set;}
公共字符串[]大小{get;set;}
}
具有JsonSerialization的公共类词典:IDictionary,INotifyPropertyChanged{
#地区活动
公共事件属性更改事件处理程序属性更改;
#端区
#区域专用字段
词典;
#端区
#区域构造函数
使用JsonSerialization()的公共词典{
_interalDictionary=新字典();
}
#端区
#IDictionary接口的区域实现
公共TValue此[TKey]{
得到{
试一试{
返回值(TValue)_区间[key];
}
捕获(例外情况除外){
返回默认值(TValue);
}
}
设置{
_内部字典[键]=值;
NotifyObserversOfChange();
}
}
公共ICollection密钥{
得到{
return _interalDictionary.Select(x=>(TKey)x.Key).ToList();
}
}
公共ICollection值{
得到{
return _interalDictionary.Select(x=>(TValue)x.Value).ToList();
}
}
公共整数计数{
得到{
返回_interalDictionary.Count;
}
}
公共图书馆是只读的{
得到{
返回false;
}
}
公共无效添加(TKey键,TValue值){
_添加(键、值);
NotifyObserversOfChange();
}
公共作废添加(KeyValuePair项){
_添加(item.Key,item.Value);
NotifyObserversOfChange();
}
公共空间清除(){
_interalDictionary=新字典();
NotifyObserversOfChange();
}
public bool包含(KeyValuePair项){
return _interalDictionary.Contains(项目);
}
公共bool ContainsKey(TKey){
返回_interalDictionary.ContainsKey(键);
}
public void CopyTo(KeyValuePair[]数组,int-arrayIndex){
抛出新的NotImplementedException();
}
公用门移除(TKey){