I am serializing an object and storing it on a file using one assembly and reading it and deserializing it using a different assembly. When the second assembly attempts to deserialize the object I get back the following error: Unable to find assembly 'CreateData, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

Googling around I found that in order to solve my problem I have to bind the deserializer to the new assembly, the one that does the reading; however when I try to implement the code I found, I get back exactly the same message.

I found that in the ReadData program when the BindChanger method executes, typeTodeserialize returns null and I can’t figure out why. Can someone point me in the right direction? What am I doing wrong in BindChanger that cause it to return null?


Thanks,

Enrique


Here is the code that reads the file

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Reflection;

namespace ReadData
{
    class Program
    {
        static void Main()
        {
            // Construct the object that will receive the data
            DataStructure ds = null;

            // Open the data file
            FileStream fs = new FileStream("DataFile.dat", FileMode.Open);

            // Construct the binary formatter
            BinaryFormatter bf = new BinaryFormatter();

            // Change the binding
            bf.Binder = new BindChanger();

            // deserialize
            ds = (DataStructure)bf.Deserialize(fs);
            fs.Close();

            // Announce success
            Console.WriteLine("File Data");
            Console.WriteLine("x = {0}, y = {1}", ds.x, ds.y);
            Console.WriteLine("Press enter to exit");
            Console.ReadLine();
        }
    }

    class BindChanger : System.Runtime.Serialization.SerializationBinder
    {
        public override Type BindToType(string assemblyName, string typeName)
        {
            // Define the new type to bind to
            Type typeToDeserialize = null;

            // Get the current assembly
            string currentAssembly = Assembly.GetExecutingAssembly().FullName;

            // Create the new type and return it
            typeToDeserialize = Type.GetType(string.Format("{0}, {1}", typeName, currentAssembly));

            return typeToDeserialize;
        }
    }

    [Serializable]
    class DataStructure
    {
        public int x;
        public int y;
    }
}

and this is the code that creates the file

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace CreateData
{
    class Program
    {
        static void Main()
        {
            // Construct and fill the data structure
            DataStructure theData = new DataStructure();
            theData.x = 123;
            theData.y = 456;

            // Open a stream for writing
            FileStream fs = new FileStream("DataFile.dat", FileMode.Create);

            // Construct a binary formatter and
            // serialize the data to a stream
            BinaryFormatter bf = new BinaryFormatter();
            bf.Serialize(fs, theData);
            fs.Close();

            // Announce success
            Console.WriteLine("Data file created, press Enter to exit");
            Console.ReadLine();
        }
    }

    [Serializable]
    class DataStructure
    {
        public int x;
        public int y;
    }
}

Enrique,

It's because you declare the class "DataStructure" within the namespace of "CreateFile". When the file is created, the class is serialized with the namespace under which it was created. When the ReadFile project comes along, it cannot resolve the "CreateFile" namespace that's in the data file.

Try this: declare a separate C# file (call it DataStructure.cs) and move your declaration of the DataStructure class into it (you will have to change the [Serializable] tag to [System.Serializable]). Remove the DataStructure declarations from both the CreateData and ReadData classes. Include the DataStructure.cs file into both projects.

Should work a whole lot better.

> Unable to find assembly 'CreateData, Version=1.0.0.0,

I think you forget to use same namespace for type - DataStructure.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace CreateData
{
    class Program
    {
        static void Main()
        {
            // Construct and fill the data structure
            Test.DataStructure theData = new Test.DataStructure();
            theData.x = 123;
            theData.y = 456;

            // Open a stream for writing
            FileStream fs = new FileStream(@"c:\csnet\DataFile.dat", FileMode.Create);

            // Construct a binary formatter and
            // serialize the data to a stream
            BinaryFormatter bf = new BinaryFormatter();
            bf.Serialize(fs, theData);
            fs.Close();

            // Announce success
            Console.WriteLine("Data file created, press Enter to exit");
            Console.ReadLine();
        }
    }
}

namespace Test
{
    [Serializable]
    class DataStructure
    {
        public int x;
        public int y;
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Reflection;
using System.Security.Permissions;
namespace ReadData
{
    class Program
    {
        static void Main()
        {
            // Construct the object that will receive the data
            Test.DataStructure ds = null;

            // Open the data file
            FileStream fs = new FileStream(@"c:\csnet\DataFile.dat", FileMode.Open);

            // Construct the binary formatter
            BinaryFormatter bf = new BinaryFormatter();
            bf.AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;

            // Change the binding
            bf.Binder = new BindChanger();

            // deserialize

            ds = (Test.DataStructure)bf.Deserialize(fs);
            fs.Close();

            // Announce success
            Console.WriteLine("File Data");
            Console.WriteLine("x = {0}, y = {1}", ds.x, ds.y);
            Console.WriteLine("Press enter to exit");
            Console.ReadLine();
        }
    }

    class BindChanger : System.Runtime.Serialization.SerializationBinder
    {
        public override Type BindToType(string assemblyName, string typeName)
        {
            // Define the new type to bind to
            Type typeToDeserialize = null;

            // Get the current assembly
            string currentAssembly = Assembly.GetExecutingAssembly().FullName;
           
            // Create the new type and return it
            typeToDeserialize = Type.GetType(string.Format("{0}, {1}", typeName, currentAssembly));

            return typeToDeserialize;
        }
    }
}
namespace Test
{
    [Serializable]
    class DataStructure
    {
        public int x;
        public int y;
    }
}

Enrique,

It's because you declare the class "DataStructure" within the namespace of "CreateFile". When the file is created, the class is serialized with the namespace under which it was created. When the ReadFile project comes along, it cannot resolve the "CreateFile" namespace that's in the data file.

Try this: declare a separate C# file (call it DataStructure.cs) and move your declaration of the DataStructure class into it (you will have to change the [Serializable] tag to [System.Serializable]). Remove the DataStructure declarations from both the CreateData and ReadData classes. Include the DataStructure.cs file into both projects.

Should work a whole lot better.

It worked only after I separated the data structure to a separate file and a different namespace.


Thanks

Hello again,

I had to reopen the thread because a similar error appeared when I tried to solve my real life problem.

When I execute the program that reads the data I get the message: Unable to load type System.Collections.Generic.List`1[[TheData.DataElement, CreateData, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] required for deserialization.

The code that creates the data is:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using TheData;

namespace CreateData
{
    class Program
    {
        static void Main()
        {
            // Construct and fill the data structure
            DataStructure dataItems = new DataStructure();
            DataElement createdItem = new DataElement();

            createdItem.x = 10;
            createdItem.y = 15;
            createdItem.numberSize = size.large;
            dataItems.item.Add(createdItem);

            createdItem.x = 22;
            createdItem.y = 44;
            createdItem.numberSize = size.small;
            dataItems.item.Add(createdItem);

            // Open a stream for writing
            FileStream fs = new FileStream("DataFile.dat", FileMode.Create);

            // Construct a binary formatter and
            // serialize the data to a stream
            BinaryFormatter bf = new BinaryFormatter();
            bf.Serialize(fs, dataItems);
            fs.Close();

            // Announce success
            Console.WriteLine("Data file created, press Enter to exit");
            Console.ReadLine();
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace TheData
{
    [Serializable]
    class DataStructure
    {
        public List<DataElement> item = new List<DataElement>();
    }

    [Serializable]
    struct DataElement
    {
        public int x;
        public int y;
        public size numberSize;
    }

    enum size
    {
        small = 1,
        large = 2
    }
}

The program that reads the data is:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Reflection;
using TheData;

namespace ReadData
{
    class Program
    {
        static void Main()
        {
            // Construct the object that will receive the data
            TheData.DataStructure ds = null;

            // Open the data file
            FileStream fs = new FileStream("DataFile.dat", FileMode.Open);

            // Construct the binary formatter
            BinaryFormatter bf = new BinaryFormatter();

            // Change the binding
            bf.Binder = new BindChanger();

            // deserialize
            ds = (TheData.DataStructure)bf.Deserialize(fs);
            fs.Close();

            // Announce success
            Console.WriteLine("File Data");
            Console.ReadLine();
        }
    }

    class BindChanger : System.Runtime.Serialization.SerializationBinder
    {
        public override Type BindToType(string assemblyName, string typeName)
        {
            // Define the new type to bind to
            Type typeToDeserialize = null;

            // Get the assembly names
            string currentAssembly = Assembly.GetExecutingAssembly().FullName;

            // Create the new type and return it
            typeToDeserialize = Type.GetType(string.Format("{0}, {1}", typeName, currentAssembly));
            return typeToDeserialize;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace TheData
{
    [Serializable]
    class DataStructure
    {
        public List<DataElement> item = new List<DataElement>();
    }

    [Serializable]
    struct DataElement
    {
        public int x;
        public int y;
        public size numberSize;
    }

    enum size
    {
        small = 1,
        large = 2
    }
}

Again your help will be greatly appreciated as I already los track of how much time I have invested in this problem.

Enrique

Here is a link that describes a situation similar to yours:

http://www.dotnet4all.com/dotnet-code/2004/12/serialization-headaches.html

The poster suggests that perhaps you develop a separate assembly (DLL) that does all of the serialization/de-serialization. Then call that from your CreateData and ReadData programs.

If you examine the contents of "DataFile.dat" in an editor capable of viewing hex, you can see that the "CreateData" assembly is tagged to the data in file. When your ReadData program comes along and attempts to read the data, you get the error.

One assembly that reads and writes the data would alleviate that issue.

Hope this helps.

I got the CreateData and ReadData programs to work this way; the problem is I’ll have to rewrite part of my application.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.