Reputation: 558
When I create a ViewModel with a ReactiveList
and an IReactiveDerivedList
and then serialize and deserialize it using Json.net, the derived list seems to be broken. What am I doing wrong?
The viewmodel:
[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);
}
}
The serialization test:
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
}
Upvotes: 1
Views: 139
Reputation: 1190
I think the issue here is that when the ViewModel is deserialized, the ReactiveList used as the source for the derived list is also deserialized, which is where the problem lies.
When your TestViewModel is deserialized, the order of events goes something like this:
The last step is where the issue occurs. The derived collection is subscribed to the old observables, not the ones that are now being used by the ReactiveList. One way to fix it would be to give the derived list property a private setter, implement a deserialization callback, and create the derived list in that 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);
}
}
Upvotes: 2