Implementing Persistence in an Add-in - deserialization does not work

685
2
Jump to solution
08-21-2012 10:07 AM
SteffanVoss
New Contributor II
Hi,

I followed the LogExtension example http://help.arcgis.com/en/sdk/10.0/arcobjects_net/conceptualhelp/index.html#/Sample_Persisting_data_...

and I have the some problem with the binaryFormatter and the SerializationHelper

 protected override void OnSave(Stream outStrm)         {             base.OnSave(outStrm);              //PersistenceHelper.Save<SerializableObserveableCollection<ESRI.ArcGIS.Carto.ILayer>>(outStrm, availableLayer);             var bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();              //bf.Serialize(outStrm, availableLayer);             PersistenceHelper.Save<ObservableCollection<Layer>>(outStrm, availableLayer);         }          protected override void OnLoad(Stream inStrm)         {             base.OnLoad(inStrm);              //SerializableObserveableCollection<ESRI.ArcGIS.Carto.ILayer> o = new SerializableObserveableCollection<ESRI.ArcGIS.Carto.ILayer>();              var bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();              availableLayer = new ObservableCollection<Layer>();             //availableLayer = (ObservableCollection <Layer>) bf.Deserialize(inStrm);             PersistenceHelper.Load<ObservableCollection<Layer>>(inStrm, ref availableLayer);         }


The OnSave methods seems to work fine, but the Load call returns with:

Unable to find assembly 'MCDA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

According to "the internet" this is usually the case if two different applications(assemblies) try to work on the same data, which is not the case.

I have no idea how to solve this...
0 Kudos
1 Solution

Accepted Solutions
SteffanVoss
New Contributor II
In my Add-in, I used the following code. I've serialized a dictionary in the OnSave sub

    Protected Overrides Sub OnLoad(ByVal inStrm As System.IO.Stream)         'MyBase.OnLoad(inStrm)          Dim binaryFormatter = New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter()          Try             theDict = CType(binaryFormatter.Deserialize(inStrm), Dictionary(Of Object, Object))             If theDict.Count > 0 Then CreateRenderer()          Catch ex As Exception             System.Windows.Forms.MessageBox.Show(ex.ToString, "Extension: OnLoad")         End Try      End Sub


I think that is what I did.
However I have learned two things...

The first is that it is required (at least for me) to define my own SerializationBinder:

sealed class MCDADeserializationBinder : SerializationBinder     {         public override Type BindToType(string assemblyName, string typeName)         {             return Type.GetType(typeName + "," + Assembly.GetExecutingAssembly().FullName);         }     }


Moreover it seems that is possible to serialize self created objects, but it is not possible to serialize them in a List or something generic. That is also true if you implement the suggested interfaces form ESRI or Microsoft. So I have to do some workarounds by saving only plain strings in List.

That works for me:

protected override void OnSave(Stream outStrm)         {              var bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();              //persist onlz the unique layer names of selected layer             _listOfSelectedUniqueLayerNamesForPersistence = _listOfAvailableLayer.Where(l => l.isSelected).Select(l => l.UniqueLayerName).ToList();                           bf.Serialize(outStrm, _listOfSelectedUniqueLayerNamesForPersistence);         }          protected override void OnLoad(Stream inStrm)         {             var bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();              //bf.AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;              bf.Binder = new MCDADeserializationBinder();              _listOfSelectedUniqueLayerNamesForPersistence = null;             _listOfSelectedUniqueLayerNamesForPersistence = bf.Deserialize(inStrm) as List<string>;         }  

View solution in original post

0 Kudos
2 Replies
KenBuja
MVP Esteemed Contributor
In my Add-in, I used the following code. I've serialized a dictionary in the OnSave sub

    Protected Overrides Sub OnLoad(ByVal inStrm As System.IO.Stream)
        'MyBase.OnLoad(inStrm)

        Dim binaryFormatter = New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter()

        Try
            theDict = CType(binaryFormatter.Deserialize(inStrm), Dictionary(Of Object, Object))
            If theDict.Count > 0 Then CreateRenderer()

        Catch ex As Exception
            System.Windows.Forms.MessageBox.Show(ex.ToString, "Extension: OnLoad")
        End Try

    End Sub
0 Kudos
SteffanVoss
New Contributor II
In my Add-in, I used the following code. I've serialized a dictionary in the OnSave sub

    Protected Overrides Sub OnLoad(ByVal inStrm As System.IO.Stream)         'MyBase.OnLoad(inStrm)          Dim binaryFormatter = New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter()          Try             theDict = CType(binaryFormatter.Deserialize(inStrm), Dictionary(Of Object, Object))             If theDict.Count > 0 Then CreateRenderer()          Catch ex As Exception             System.Windows.Forms.MessageBox.Show(ex.ToString, "Extension: OnLoad")         End Try      End Sub


I think that is what I did.
However I have learned two things...

The first is that it is required (at least for me) to define my own SerializationBinder:

sealed class MCDADeserializationBinder : SerializationBinder     {         public override Type BindToType(string assemblyName, string typeName)         {             return Type.GetType(typeName + "," + Assembly.GetExecutingAssembly().FullName);         }     }


Moreover it seems that is possible to serialize self created objects, but it is not possible to serialize them in a List or something generic. That is also true if you implement the suggested interfaces form ESRI or Microsoft. So I have to do some workarounds by saving only plain strings in List.

That works for me:

protected override void OnSave(Stream outStrm)         {              var bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();              //persist onlz the unique layer names of selected layer             _listOfSelectedUniqueLayerNamesForPersistence = _listOfAvailableLayer.Where(l => l.isSelected).Select(l => l.UniqueLayerName).ToList();                           bf.Serialize(outStrm, _listOfSelectedUniqueLayerNamesForPersistence);         }          protected override void OnLoad(Stream inStrm)         {             var bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();              //bf.AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;              bf.Binder = new MCDADeserializationBinder();              _listOfSelectedUniqueLayerNamesForPersistence = null;             _listOfSelectedUniqueLayerNamesForPersistence = bf.Deserialize(inStrm) as List<string>;         }  
0 Kudos