反序列化后 IReactiveDerivedList 损坏
IReactiveDerivedList broken after deserialization
当我使用 ReactiveList
和 IReactiveDerivedList
创建 ViewModel,然后使用 Json.net 对其进行序列化和反序列化时,派生列表似乎已损坏。我做错了什么?
视图模型:
[DataContract]
public class TestViewModel : ReactiveObject
{
[DataMember]
public ReactiveList<int> List { get; } = new ReactiveList<int>();
public IReactiveDerivedList<int> DerivedList { get; }
public TestViewModel()
{
//DerivedList contains all elements of List that are greater than 0.
DerivedList = List.CreateDerivedCollection(v => v, v => v > 0);
}
}
序列化测试:
private void Example()
{
TestViewModel vm = new TestViewModel();
vm.List.Add(0);
vm.List.Add(1);
//vm.DerivedList now has 1 item
string json = JsonConvert.SerializeObject(vm);
TestViewModel clone = JsonConvert.DeserializeObject<TestViewModel>(json);
//vm.DerivedList now has 1 item
//clone.DerivedList now has 1 item
vm.List.Add(1);
clone.List.Add(1);
//vm.DerivedList now has 2 items
//clone.DerivedList now has 1 item
}
我认为这里的问题是当ViewModel被反序列化时,作为派生列表源的ReactiveList也被反序列化,这就是问题所在。
当你的 TestViewModel 被反序列化时,事件的顺序是这样的:
- ReactiveList constructor runs. This sets up 可观察的支持字段。
- TestViewModel 构造函数运行。这将设置派生集合,该集合订阅 ReactiveList 上的可观察对象。
- ReactiveList "OnDeserialized" callback runs. This sets up 可观察支持字段再次,覆盖它们以前的值。
最后一步是出现问题的地方。派生集合订阅了 old observables,而不是 ReactiveList 现在正在使用的那些。修复它的一种方法是为派生列表 属性 提供一个私有 setter,实现一个 deserialization callback,并在该回调中创建派生列表。
[DataContract]
public class TestViewModel : ReactiveObject
{
[DataMember]
public ReactiveList<int> List { get; } = new ReactiveList<int>();
public IReactiveDerivedList<int> DerivedList { get; private set; }
public TestViewModel()
{
SetupRx();
}
[OnDeserialized]
internal void OnDeserialized(StreamingContext context)
{
SetupRx();
}
private void SetupRx()
{
DerivedList?.Dispose();
DerivedList = List.CreateDerivedCollection(v => v, v => v > 0);
}
}
当我使用 ReactiveList
和 IReactiveDerivedList
创建 ViewModel,然后使用 Json.net 对其进行序列化和反序列化时,派生列表似乎已损坏。我做错了什么?
视图模型:
[DataContract]
public class TestViewModel : ReactiveObject
{
[DataMember]
public ReactiveList<int> List { get; } = new ReactiveList<int>();
public IReactiveDerivedList<int> DerivedList { get; }
public TestViewModel()
{
//DerivedList contains all elements of List that are greater than 0.
DerivedList = List.CreateDerivedCollection(v => v, v => v > 0);
}
}
序列化测试:
private void Example()
{
TestViewModel vm = new TestViewModel();
vm.List.Add(0);
vm.List.Add(1);
//vm.DerivedList now has 1 item
string json = JsonConvert.SerializeObject(vm);
TestViewModel clone = JsonConvert.DeserializeObject<TestViewModel>(json);
//vm.DerivedList now has 1 item
//clone.DerivedList now has 1 item
vm.List.Add(1);
clone.List.Add(1);
//vm.DerivedList now has 2 items
//clone.DerivedList now has 1 item
}
我认为这里的问题是当ViewModel被反序列化时,作为派生列表源的ReactiveList也被反序列化,这就是问题所在。
当你的 TestViewModel 被反序列化时,事件的顺序是这样的:
- ReactiveList constructor runs. This sets up 可观察的支持字段。
- TestViewModel 构造函数运行。这将设置派生集合,该集合订阅 ReactiveList 上的可观察对象。
- ReactiveList "OnDeserialized" callback runs. This sets up 可观察支持字段再次,覆盖它们以前的值。
最后一步是出现问题的地方。派生集合订阅了 old observables,而不是 ReactiveList 现在正在使用的那些。修复它的一种方法是为派生列表 属性 提供一个私有 setter,实现一个 deserialization callback,并在该回调中创建派生列表。
[DataContract]
public class TestViewModel : ReactiveObject
{
[DataMember]
public ReactiveList<int> List { get; } = new ReactiveList<int>();
public IReactiveDerivedList<int> DerivedList { get; private set; }
public TestViewModel()
{
SetupRx();
}
[OnDeserialized]
internal void OnDeserialized(StreamingContext context)
{
SetupRx();
}
private void SetupRx()
{
DerivedList?.Dispose();
DerivedList = List.CreateDerivedCollection(v => v, v => v > 0);
}
}