Serialization Exception when openning Dictionary<> from different framework
When I try to open a PsiStore collected in a different framework (.NET Core) in a .NET framework program a serialization error is thrown:
System.Runtime.Serialization.SerializationException
HResult=0x8013150C
Message=The schema System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Int32, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e version 2 (implemented by System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.Int32, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e) is missing the following members required in the current version of System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089: buckets,entries,count,version,freeList,freeCount,comparer,keys,values,_syncRoot
Source=Microsoft.Psi
StackTrace:
at Microsoft.Psi.Serialization.TypeSchema.ValidateCompatibleWith(TypeSchema other)
at Microsoft.Psi.Serialization.TypeSchema.GetCompatibleMemberSet(TypeSchema targetSchema)
at Microsoft.Psi.Serialization.ClassSerializer`1.Initialize(KnownSerializers serializers, TypeSchema targetSchema)
at Microsoft.Psi.Serialization.KnownSerializers.AddHandler[T]()
at Microsoft.Psi.Serialization.KnownSerializers.GetHandler[T]()
at Microsoft.Psi.Components.DeserializerComponent`1..ctor(Pipeline pipeline, KnownSerializers serializers, T reusableInstance)
at Microsoft.Psi.Data.Importer.OpenStream[T](String streamName, T reusableInstance)
at psi_dict_test.Program.Read() in D:\psi-dict-test\Program.cs:line 26
at psi_dict_test.Program.Main(String[] args) in D:\psi-dict-test\Program.cs:line 35
I also find the reverse to be true too, but interestingly no error is thrown in PsiStudio. Here is the code that generates the PsiStores:
namespace psi_dict_test
{
using System;
using System.Collections.Generic;
using Microsoft.Psi;
class Program
{
static void Write()
{
using (var p = Pipeline.Create())
{
var gen = Generators.Repeat(p, new Dictionary<string, int>() { { "hello", 1} }, 1, TimeSpan.Zero);
var store = Store.Create(p, "write-w-core", "store");
gen.Write("dict", store);
p.Run();
}
}
static void Read()
{
using (var p = Pipeline.Create())
{
var store = Store.Open(p, "write-w-core", "store");
store.OpenStream<Dictionary<string, int>>("dict").Do(m =>{
Console.WriteLine(m["hello"]);
});
p.Run();
}
}
static void Main(string[] args)
{
Read();
}
}
}
Here are the two generated PsiStores: write-w-core.0000.zip write-w-framework.0000.zip
Similar exception is also thrown for Shared<Image> streams.
I also just found out that the problem carries over to PsiStudio. Certain visualizations fail if using .NET Core.
Unfortunately there are indeed a number of issues with serialization between .NET Core and .NET Framework types. We will address some of these in the upcoming release, but unfortunately Dictionary won't be among them. We plan to address this soon though but it will require some rework on parts of the serialization system.
In the meantime, one workaround is to flatten and re-export your dictionary data as an array of (string, int)[] (which will still be subject to issue #75 that you identified, but that one should be fixed soon).
Thanks for getting back to me so quickly!
Good to hear that some of these will be fixed soon. Unfortunately, the dict here is a stand in for a way more complicated List<AzureKinectBody> stream. I was wondering if you can tell which, if any, of the following streams might be address in the upcoming release?
- (System.Collections.Generic.List`1[[MathNet.Spatial.Euclidean.CoordinateSystem)
- MathNet.Spatial.Euclidean.CoordinateSystem
- System.Collections.Generic.List`1[[Microsoft.Psi.AzureKinect.AzureKinectBody
- Microsoft.Psi.Shared`1[[Microsoft.Psi.Imaging.EncodedImage
Thanks for the help, these workarounds probably can tie more over until the next release.
For the types 1 through 4 above, are you generating/capturing these in .NET Core and trying to visualize them in PsiStudio (.NET Framework)?
For types such as CoordinateSystem and Shared<Image>, these should work cross-framework with the next release. However we will have to do more investigation into the issue with Dictionary which our serialization system cannot currently deal with in a cross-framework compatible way, so unfortunately any types that contain a Dictionary (such as AzureKinectBody) will have the same problem as the one you have already run into. I'm sorry this isn't more helpful for the moment, but we will definitely be looking into this soon.
I actually have plans for both directions. Here's my original plan:
- Core -> Framework. PsiStores that are collected with .NET Core with the goal of replaying it in PsiStudio.
- Framework -> Core: Instead of sending it through ROS and running two computer simultaneously for testing, I was hoping to just run my Linux machine with ROS and playback the recorded data with a .NET Core application. That is when I first ran into this issue.
I guess this is all the technical debt I get from running a hybrid Psi/ROS system. These issues aren't blocking my main application just some debugging/QOL stuff I want to have to help debugging. I probably will write some specific encoder/decoder with the flattening trick for AzureKinectBody until it is address in a future version.
Thanks for the help @chitsaw, I guess I am pushing the boundaries of what Psi was originally made for :P