连载自定义集合具有附加属性,并添加到项目联播事件propertChanged [英] Serialise custom collection With additional properties and on Add to hookup item propertChanged events
问题描述
我有一个自定义集合,我想与JSON.NET以连载:
我需要它这个定义集合中连载的子集合
在deserialisation我需要挂钩PropertyChanged事件为集合内的项目。
如果我通过我的收藏原样, JSON看到IEnumerable和串行化集合确定的项目,但忽略了内部的其他集合。
如果我的属性集合与[JSONObject的],将连载内部所有藏品但不是内部_list;
如果我添加[JsonProperty]到内部_list这将连载所有集合。
但由于它设置_list作为反序列化过程中一个属性的添加我的自定义集合的方法是不叫,并作为项目_list内所以的PropertyChanged事件从来没有得到勾搭上了。
我试图隐藏内部_list和一个公共的getter setter方法包装它,我想,如果反序列化期间,它使用的公共setter方法来设置内部_list我可以附加到项事件出现,但这并不能工作。
有什么反序列化期间我可以做,以获得notifyproperty改变了项目的事件在内部?
_list迷上了编辑:我试过一个转换器:
公共类TrackableCollectionConverter:JsonConverter
{
公众覆盖布尔CanConvert(类型的objectType)
{
返回的objectType == typeof运算(TrackableCollectionCollection< ITrackableEntity>);
}
公众覆盖对象ReadJson(
JsonReader读者,类型的objectType,
对象existingValue,JsonSerializer串行)
{
// N.B.空值处理缺少
变种替代= serializer.Deserialize< TrackableCollectionCollection< ITrackableEntity>>(读卡器);
变种trackableCollection =新TrackableCollectionCollection< ITrackableEntity>();
的foreach(VAR EL在代理)
trackableCollection.Add(EL);
的foreach(VAR EL在surrogate.NewItems)
trackableCollection.NewItems.Add(EL);
的foreach(VAR EL在surrogate.ModifiedItems)
trackableCollection.ModifiedItems.Add(EL);
的foreach(VAR EL在surrogate.DeletedItems)
trackableCollection.DeletedItems.Add(EL);
返回trackableCollection;
}
公共覆盖无效WriteJson(JsonWriter作家,对象的值,
JsonSerializer串行)
{
serializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
serializer.Serialize(作家,价值);
}
}
给出错误:
{消息:发生错误,ExceptionMessage:在'ObjectContent`1类型没有序列化反应机构内容类型应用/ JSON的;字符集= UTF-8',ExceptionType。:System.InvalidOperationException,堆栈跟踪:空的InnerException:{消息:出现错误, ExceptionMessage:国有财产令牌属性名会导致一个无效的JSON对象路径'[0]',ExceptionType。:Newtonsoft.Json.JsonWriterException,堆栈跟踪:在Newtonsoft.Json.JsonWriter。自动完成(JsonToken tokenBeingWritten)\r\\\
在Newtonsoft.Json.JsonWriter.InternalWritePropertyName(字符串名称)\r\\\
在Newtonsoft.Json.JsonTextWriter.WritePropertyName(字符串名称,布尔逃生)\r\\\
在Newtonsoft.Json.Serialization.JsonProperty.WritePropertyName(JsonWriter作家)\r\\\
在Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter作家,对象的值,JsonObjectContract合同,JsonProperty成员,JsonContainerContract collectionContract,JsonProperty containerProperty)\\在Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList \\r\\\
在Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter作家,对象的值,JsonContract valueContract,JsonProperty成员,JsonContainerContract containerContract,JsonProperty containerProperty)\r\\\
(JsonWriter作家,IEnumerable的值,JsonArrayContract合同,JsonProperty成员,JsonContainerContract collectionContract,JsonProperty containerProperty)\r\\\
在Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter作家,对象的值,JsonContract valueContract,JsonProperty成员,JsonContainerContract containerContract ,JsonProperty containerProperty在Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter,对象的值,类型的objectType)\r\\\
)\r\\\
在Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter,对象的值,类型的objectType在Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter,对象的值)\r\\\
在System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(类型类型,对象的值)\r\\\
,流writeStream,编码effectiveEncoding)\r\\\
在System.Net.Http.Formatting.JsonMediaTypeFormatter.WriteToStream(类型类型,对象的值,流writeStream,编码effectiveEncoding)\r\\\
在System.Net.Http。 Formatting.BaseJsonMediaTypeFormatter.WriteToStream(类型类型,对象的值,流writeStream,HttpContent内容)\r\\\
在System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStreamAsync(类型类型,对象的值,流writeStream,HttpContent内容,TransportContext transportContext,的CancellationToken的CancellationToken)\r\\\
---从以前的位置堆栈跟踪,其中引发异常--- \r\\\
在System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)结束\ r\\\
在System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)\r\\\
在System.Runtime.CompilerServices.TaskAwaiter.GetResult()\r\\\
在System.Web.Http.WebHost .HttpControllerHandler.d__1b.MoveNext()}}
块引用>
这里是收集,因为我有这么远。
[Serializable接口]
[JSONObject的]
[JsonConverter(typeof运算(TrackableCollectionConverter))]
公共类TrackableCollectionCollection< T> :IList的< T>其中T:ITrackableEntity
{
[JsonIgnore]
&IList的LT; T> _list =新的List< T>();
[JsonProperty]
公众的IList< T>表
{
{返回_list; }
组
{
_list =价值;
的foreach(在_list VAR项)
item.PropertyChanged + = item_PropertyChanged;
}
}
[数据成员]
公众的IList< T> NewItems
{
{返回_newItems; }
}
&IList的LT; T> _newItems =新的List< T>();
[数据成员]
公众的IList< T> ModifiedItems
{
{返回_modifiedChildren; }
}
&IList的LT; T> _modifiedChildren =新的List< T>();
[数据成员]
公众的IList< T> DeletedItems
{
{返回_deletedItems; }
}
&IList的LT; T> _deletedItems =新的List< T>(); T>的IEnumerable
公众的IEnumerator<的
#地区的实施情况;的GetEnumerator()
{
返回_list.GetEnumerator();
}
的IEnumerator IEnumerable.GetEnumerator()
{
返回的GetEnumerator();
} $ B的ICollection<的
$ B #endregion
#地区的实施情况; T>
公共无效添加(T项目)
{
如果(item.Id.Equals(默认值(GUID)))
_newItems.Add(项目);
,否则
{
//我想过这样做,但将螺丝EF对象生成。
//抛出新NotSupportedException异常();
}
item.PropertyChanged + = item_PropertyChanged;
_list.Add(项目);
}
公共无效清除()
{
NewItems.Clear();
ModifiedItems.Clear();
的foreach(在_list VAR项)
{
item.PropertyChanged - = item_PropertyChanged;
DeletedItems.Add(项目);
}
_list.Clear();
}
公共BOOL包含(T项目)
{
返回_list.Contains(项目);
}
公共无效CopyTo从(T []数组,INT arrayIndex)
{
_list.CopyTo(数组,arrayIndex);
}
公共BOOL删除(T项目)
{
如果(NewItems.Contains(项目))
NewItems.Remove(项目);
如果(ModifiedItems.Contains(项目))
ModifiedItems.Remove(项目);
如果
DeletedItems.Add(项目)(DeletedItems.Contains(项目)!);
返回_list.Remove(项目);
}
公众诠释伯爵
{
{返回_list.Count; }
}
公共BOOL IsReadOnly
{
{返回_list.IsReadOnly; }
} $ B的IList<的
$ B #endregion
#地区的实施情况; T>
公众诠释的IndexOf(T项目)
{
返回_list.IndexOf(项目);
}
公共无效插入(INT指数,T项目)
{
如果(item.Id.Equals(默认值(GUID)))
_newItems.Add(项目);
,否则
{
//我想过这样做,但将螺丝EF对象生成。
//抛出新NotSupportedException异常();
}
item.PropertyChanged + = item_PropertyChanged;
_list.Insert(索引项);
}
公共无效RemoveAt移除(INT指数)
{
VAR项目=本[指数]
如果(NewItems.Contains(项目))
NewItems.Remove(项目);
如果(ModifiedItems.Contains(项目))
ModifiedItems.Remove(项目);
如果
DeletedItems.Add(项目)(DeletedItems.Contains(项目)!);
_list.RemoveAt(指数);
}
公共牛逼这个[INT指数]
{
{返回_list [指数] }
集合{_list [指数] =值; }
}
#endregion
无效item_PropertyChanged(对象发件人,System.ComponentModel.PropertyChangedEventArgs E)
{
如果(((T)发送方).Id.Equals (默认值(GUID)))
的回报; //该项目已经在newItems收集
如果(ModifiedItems.Contains((T)发送者))
的回报;
ModifiedItems.Add((T)发送者);
}
}
解决方案您可以序列自定义容器作为
的JSONObject
,因为你现在正在做,并序列嵌入列表作为代理的的ObservableCollection< T>
。然后,你可以听在添加和移除到代理,并相应地处理它们。注 - 无需定制JsonConverter。因为我没有你的ITrackableEntity
,这里有一个快速的原型包装的IList<定义; T>
为列表< T>
:[Serializable接口]
[的JSONObject]
公共类ListContainer< T> :IList的< T>
{
[JsonIgnore]
只读表< T> _list =新的List< T>();
[JsonProperty(列表)]
私人的IList< T> SerializableList
{
得到
{
变种代理=新的ObservableCollection< T>(_清单);
proxy.CollectionChanged + =新System.Collections.Specialized.NotifyCollectionChangedEventHandler(proxy_CollectionChanged);
返回代理;
}
组
{
_list.Clear();
_list.AddRange(值);
}
}
无效proxy_CollectionChanged(对象发件人,System.Collections.Specialized.NotifyCollectionChangedEventArgs E)
{
如果(e.Action ==系统.Collections.Specialized.NotifyCollectionChangedAction.Add)
{
的foreach(在e.NewItems.Cast< VAR项目; T>())
添加(项目);
}
,否则如果(e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove)
{
的foreach(在e.NewItems.Cast< VAR项目; T>( ))
。删除(项目);
}
,否则
{
Debug.Assert的(假);
抛出新NotImplementedException();
}
}
[JsonIgnore]
公众诠释伯爵
{
{返回_list.Count; }
}
[JsonIgnore]
公共BOOL IsReadOnly
{
{返回((IList的< T>)_名单).IsReadOnly; }
}
//超越一切这里是样板。
#地区的IList< T>会员
公众诠释的IndexOf(T项目)
{
返回_list.IndexOf(项目);
}
公共无效插入(INT指数,T项目)
{
_list.Insert(索引项);
}
公共无效RemoveAt移除(INT指数)
{
_list.RemoveAt(指数);
}
公共牛逼这个[INT指数]
{
得到
{
返回_list [指数]
}
组
{
_list [指数] =值;
}
}
#endregion
#地区的ICollection< T>会员
公共无效添加(T项目)
{
_list.Add(项目);
}
公共无效清除()
{
_list.Clear();
}
公共BOOL包含(T项目)
{
返回_list.Contains(项目);
}
公共无效CopyTo从(T []数组,INT arrayIndex)
{
_list.CopyTo(数组,arrayIndex);
}
公共BOOL删除(T项目)
{
返回_list.Remove(项目);
}
#endregion
#地区的IEnumerable< T>会员
公众的IEnumerator< T>的GetEnumerator()
{
返回_list.GetEnumerator();
}
#endregion
#地区的IEnumerable会员
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
返回的GetEnumerator();
}
#endregion
}
和然后,进行测试:
公共静态无效TestListContainerJson()
{
无功名单=新ListContainer< INT>();
list.Add(101);
list.Add(102);
list.Add(103);
VAR JSON = JsonConvert.SerializeObject(名单);
VAR newList = JsonConvert.DeserializeObject< ListContainer< INT>>(JSON);
Debug.Assert的(list.SequenceEqual(newList)); //没有断言。
}
更新
原来,Json.NET遵循相同的模式的
的XmlSerializer
:如果您序列化代理列表作为的阵列的,二传手将被称为用后完全填充的阵列读取,你可以将其添加为必需的:[Serializable接口]
[的JSONObject ]
公共类ListContainer< T> :IList的< T>
{
[JsonIgnore]
只读表< T> _list =新的List< T>();
[JsonProperty(列表)]
私人T [] SerializableList
{
得到
{
返回_list.ToArray() ;
}
组
{
清除();
的foreach(价值VAR项)
添加(项目);
}
}
[JsonIgnore]
公众诠释伯爵
{
{返回_list.Count; }
}
[JsonIgnore]
公共BOOL IsReadOnly
{
{返回((IList的< T>)_名单).IsReadOnly; }
}
//超越一切这里是样板。
}
这是比我的第一个解决方案干净多了。
此外,我怀疑你的
NewItems
和ModifiedItems
列表包含在项目的引用主_list
。默认情况下Json.NET将有效地序列化和放大器中克隆这些;反序列化。为了避免这种情况,寻找到PreserveReferencesHandling
功能。更多这里I have a custom collection which I would like to serialise with JSON.NET:
I need it to serialise the child collections within this custom collection.
On deserialisation I need to hook up PropertyChanged event for items within the collection.
If I pass my collection as is, Json sees IEnumerable and serialises the items in the collection ok, but ignores the other collections within.
If I attribute the collection with [JsonObject] it will serialise all the internal collections but not the internal _list;
if I add [JsonProperty] to the internal _list it will serialise all collections.
But since it sets the _list as a property during deserialization The Add Method of my custom collection is not called and as a therefore the propertyChanged events of the items within _list never get hooked up.
I tried hiding the internal _list and wrapping it with a public getter setter, I thought if during deserialization it used the public setter to set the internal _list I could attach to the item events there, but that does not work either.
Is there anything I can do to during deserialization to get the notifyproperty changed events of the items in the internal _list hooked up?
Edit: I tried a converter:
public class TrackableCollectionConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(TrackableCollectionCollection<ITrackableEntity>); } public override object ReadJson( JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // N.B. null handling is missing var surrogate = serializer.Deserialize<TrackableCollectionCollection<ITrackableEntity>>(reader); var trackableCollection = new TrackableCollectionCollection<ITrackableEntity>(); foreach (var el in surrogate) trackableCollection.Add(el); foreach (var el in surrogate.NewItems) trackableCollection.NewItems.Add(el); foreach (var el in surrogate.ModifiedItems) trackableCollection.ModifiedItems.Add(el); foreach (var el in surrogate.DeletedItems) trackableCollection.DeletedItems.Add(el); return trackableCollection; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { serializer.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; serializer.Serialize(writer, value); } }
Gives error:
{"Message":"An error has occurred.","ExceptionMessage":"The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.","ExceptionType":"System.InvalidOperationException","StackTrace":null,"InnerException":{"Message":"An error has occurred.","ExceptionMessage":"Token PropertyName in state Property would result in an invalid JSON object. Path '[0]'.","ExceptionType":"Newtonsoft.Json.JsonWriterException","StackTrace":" at Newtonsoft.Json.JsonWriter.AutoComplete(JsonToken tokenBeingWritten)\r\n at Newtonsoft.Json.JsonWriter.InternalWritePropertyName(String name)\r\n at Newtonsoft.Json.JsonTextWriter.WritePropertyName(String name, Boolean escape)\r\n at Newtonsoft.Json.Serialization.JsonProperty.WritePropertyName(JsonWriter writer)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)\r\n at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)\r\n at Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter, Object value)\r\n at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding)\r\n at System.Net.Http.Formatting.JsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding)\r\n at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content)\r\n at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.GetResult()\r\n at System.Web.Http.WebHost.HttpControllerHandler.d__1b.MoveNext()"}}
here is the collection as I have it so far.
[Serializable] [JsonObject] [JsonConverter(typeof(TrackableCollectionConverter))] public class TrackableCollectionCollection<T> : IList<T> where T : ITrackableEntity { [JsonIgnore] IList<T> _list = new List<T>(); [JsonProperty] public IList<T> List { get { return _list; } set { _list = value; foreach(var item in _list) item.PropertyChanged += item_PropertyChanged; } } [DataMember] public IList<T> NewItems { get { return _newItems; } } IList<T> _newItems = new List<T>(); [DataMember] public IList<T> ModifiedItems { get { return _modifiedChildren; } } IList<T> _modifiedChildren = new List<T>(); [DataMember] public IList<T> DeletedItems { get { return _deletedItems; } } IList<T> _deletedItems = new List<T>(); #region Implementation of IEnumerable public IEnumerator<T> GetEnumerator() { return _list.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } #endregion #region Implementation of ICollection<T> public void Add(T item) { if (item.Id.Equals(default(Guid))) _newItems.Add(item); else { // I thought about doing this but that would screw the EF object generation. // throw new NotSupportedException(""); } item.PropertyChanged += item_PropertyChanged; _list.Add(item); } public void Clear() { NewItems.Clear(); ModifiedItems.Clear(); foreach(var item in _list) { item.PropertyChanged -= item_PropertyChanged; DeletedItems.Add(item); } _list.Clear(); } public bool Contains(T item) { return _list.Contains(item); } public void CopyTo(T[] array, int arrayIndex) { _list.CopyTo(array, arrayIndex); } public bool Remove(T item) { if (NewItems.Contains(item)) NewItems.Remove(item); if (ModifiedItems.Contains(item)) ModifiedItems.Remove(item); if (!DeletedItems.Contains(item)) DeletedItems.Add(item); return _list.Remove(item); } public int Count { get { return _list.Count; } } public bool IsReadOnly { get { return _list.IsReadOnly; } } #endregion #region Implementation of IList<T> public int IndexOf(T item) { return _list.IndexOf(item); } public void Insert(int index, T item) { if (item.Id.Equals(default(Guid))) _newItems.Add(item); else { // I thought about doing this but that would screw the EF object generation. // throw new NotSupportedException(""); } item.PropertyChanged += item_PropertyChanged; _list.Insert(index, item); } public void RemoveAt(int index) { var item = this[index]; if (NewItems.Contains(item)) NewItems.Remove(item); if (ModifiedItems.Contains(item)) ModifiedItems.Remove(item); if (!DeletedItems.Contains(item)) DeletedItems.Add(item); _list.RemoveAt(index); } public T this[int index] { get { return _list[index]; } set { _list[index] = value; } } #endregion void item_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { if (((T)sender).Id.Equals(default(Guid))) return; // The Item is already in the newItems collection if (ModifiedItems.Contains((T)sender)) return; ModifiedItems.Add((T)sender); } }
解决方案You could serialize your custom container as a
JsonObject
, as you are doing now, and serialize the embedded list as a proxyObservableCollection<T>
. You can then listen in for additions and removals to the proxy and handle them accordingly. Note -- no custom JsonConverter required. Since I don't have your definition forITrackableEntity
, here's a quick prototype wrapperIList<T>
for aList<T>
:[Serializable] [JsonObject] public class ListContainer<T> : IList<T> { [JsonIgnore] readonly List<T> _list = new List<T>(); [JsonProperty("List")] private IList<T> SerializableList { get { var proxy = new ObservableCollection<T>(_list); proxy.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(proxy_CollectionChanged); return proxy; } set { _list.Clear(); _list.AddRange(value); } } void proxy_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add) { foreach (var item in e.NewItems.Cast<T>()) Add(item); } else if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Remove) { foreach (var item in e.NewItems.Cast<T>()) Remove(item); } else { Debug.Assert(false); throw new NotImplementedException(); } } [JsonIgnore] public int Count { get { return _list.Count; } } [JsonIgnore] public bool IsReadOnly { get { return ((IList<T>)_list).IsReadOnly; } } // Everything beyond here is boilerplate. #region IList<T> Members public int IndexOf(T item) { return _list.IndexOf(item); } public void Insert(int index, T item) { _list.Insert(index, item); } public void RemoveAt(int index) { _list.RemoveAt(index); } public T this[int index] { get { return _list[index]; } set { _list[index] = value; } } #endregion #region ICollection<T> Members public void Add(T item) { _list.Add(item); } public void Clear() { _list.Clear(); } public bool Contains(T item) { return _list.Contains(item); } public void CopyTo(T[] array, int arrayIndex) { _list.CopyTo(array, arrayIndex); } public bool Remove(T item) { return _list.Remove(item); } #endregion #region IEnumerable<T> Members public IEnumerator<T> GetEnumerator() { return _list.GetEnumerator(); } #endregion #region IEnumerable Members System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); } #endregion }
And then, to test:
public static void TestListContainerJson() { var list = new ListContainer<int>(); list.Add(101); list.Add(102); list.Add(103); var json = JsonConvert.SerializeObject(list); var newList = JsonConvert.DeserializeObject<ListContainer<int>>(json); Debug.Assert(list.SequenceEqual(newList)); // No assert. }
Update
It turns out that Json.NET follows the same pattern as
XmlSerializer
: if you serialize the proxy list as an array, the setter will be called with the fully populated array after being read, and you can add them as required:[Serializable] [JsonObject] public class ListContainer<T> : IList<T> { [JsonIgnore] readonly List<T> _list = new List<T>(); [JsonProperty("List")] private T [] SerializableList { get { return _list.ToArray(); } set { Clear(); foreach (var item in value) Add(item); } } [JsonIgnore] public int Count { get { return _list.Count; } } [JsonIgnore] public bool IsReadOnly { get { return ((IList<T>)_list).IsReadOnly; } } // Everything beyond here is boilerplate. }
This is much cleaner than my first solution.
Also, I suspect that your
NewItems
andModifiedItems
list contain references to items in the main_list
. By default Json.NET will effectively clone these during serialization & deserialization. To avoid this, look into thePreserveReferencesHandling
functionality. More here.这篇关于连载自定义集合具有附加属性,并添加到项目联播事件propertChanged的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!