Serialization Exception

Sep 19, 2008 at 11:22 PM
Edited Sep 19, 2008 at 11:26 PM
Hi,
I keep getting strange exception during deserialization.
In onclick event in one of default model views i invoke a method of a other class (included in class library PhotosTool.Model - module has reference to it) which performs deserialization:

            if (!File.Exists(FullFileName))
            {
                photoCollection = new PhotosToolPhotoCollection();
                return;
            }
            FileStream fileStream = new FileStream(FullFileName, FileMode.Open);
            BinaryFormatter formatter = new BinaryFormatter();
            photoCollection = (PhotosToolPhotoCollection)formatter.Deserialize(fileStream);
            fileStream.Close();


Simple stuff.
Serialization looks like this:
            FileStream fileStream = new FileStream(FullFileName, FileMode.Create);
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(fileStream, photoCollection);
            fileStream.Close();


If i invoke those methods from a project of any kind (or just unit tests) it works just perfect,
but when i serialize and then deserialize it back in default view of one of modules line

photoCollection = (PhotosToolPhotoCollection)formatter.Deserialize(fileStream);

throws an exception:
Unable to find assembly 'PhotosTool.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

I have no idea what to do with it.
Sep 20, 2008 at 12:49 PM
Edited Sep 20, 2008 at 12:57 PM
I've created a sample solution showing the problem

http://www.drivehq.com/file/df.aspx/publish/serializationproblem/PublicFolder/SampleToolSolution.zip

it is based on quick startups.

there is a single module that trys to save and then load collection (when you push "Go" button).
In Load method an exception occures.

As alternative i created Console application which has reference to my model. It does exactly the same as
WPF composite App but there is no exception and it works correctly.

I would appreciate any help. :)

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ModuleAView.xaml.cs
...
        private string FullFileName = "coll.dat";
        private void btnGo_Click(object sender, RoutedEventArgs e)
        {
            SampleObjectCollection coll = new SampleObjectCollection();
            coll.Add(new SampleObject {Name = "name"});
            Save(coll);
            SampleObjectCollection coll2 = Load();
        }

        public void Save(SampleObjectCollection collection)
        {
            FileStream fileStream = new FileStream(FullFileName, FileMode.Create);
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(fileStream, collection);
            fileStream.Close();
        }

        public SampleObjectCollection Load()
        {
            SampleObjectCollection coll;
            if (!File.Exists(FullFileName))
            {
                coll = new SampleObjectCollection();
                return coll;
            }
            FileStream fileStream = new FileStream(FullFileName, FileMode.Open);
            BinaryFormatter formatter = new BinaryFormatter();
            coll = (SampleObjectCollection)formatter.Deserialize(fileStream); //this throws exception
            fileStream.Close();
            return coll;
        }
...


SampleObject.cs
...
    [Serializable]
    public class SampleObject
    {
        public string Name { get; set; }
        public int otherThing { get; internal set; }
    }
...

SampleObjectCollection.cs

...
    [Serializable]
    public class SampleObjectCollection:List<SampleObject>
    {
    }
...
Sep 22, 2008 at 12:08 PM
Hi,

The CLR's serialization runtime will attempt to resolve assemblies from the default context (ie. assemblies loaded with Assembly.Load) but Prism loads assemblies in a different context (by way of Assembly.LoadFrom). I believe that is why you're seeing failures, and also explains why your unit tests work since your assemblies are loaded into the default context there.

One way of getting around this is to attach a handler to AppDomain.AssemblyResolve and help the CLR out when attempting to deserialize.

HTH,
Kent
Sep 27, 2008 at 12:35 AM
Hi,
Thanks for the answer. I used this piece of code:
 AppDomain.CurrentDomain.AssemblyResolve += 
        delegate(object sender, ResolveEventArgs args) 
        { 
          foreach (var asm in AppDomain.CurrentDomain.GetAssemblies()) 
            if (asm.FullName == args.Name) 
              return asm; 
          return null
        }; 
posted on MSDN forum and it solved the problem.

Regards,
PK