Harald,
Why not specify a redirection for your application? You can specify
that when the old version of the library is specified, you use the new
version.
If that doesn't work, I would set a reference to both dlls and then set
up aliases for them so that you can use both versions in your application.
Of course, this would require you to switch based on which version you are
working with, providing a shim to make it easier to use, most likely (so you
don't have to switch on every call).
Hope this helps.
--
- Nicholas Paldino [.NET/C# MVP]
-
(E-Mail Removed)
"Harold Howe" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
>
> I am having a problem deserializing objects from a library when the
> following conditions exist:
>
> 1- The library is strongly named
> 2- The serialized file was created with version 1.0 of the assembly
> 3- I am trying to deserialize from an EXE that references version 2.0 of
> the assembly
> 4- Both version 1.0 and 2.0 of the assembly reside in the GAC (no policy
> redirects exist).
>
> Note that this is not the AssemblyFormat = FormatterAssemblyStyle.Simple
> problem. It is a different issue that arises because the old DLL can still
> be loaded from the GAC.
>
> object o = null;
> Foo foo = null; // Foo is in the strong named assembly
>
> BinaryFormatter formatter = new BinaryFormatter();
> formatter.AssemblyFormat = FormatterAssemblyStyle.Simple;
> using(FileStream stream = File.OpenRead("foo.bin"))
> {
> o = formatter.Deserialize(stream);
> }
>
> foo = o as Foo;
> // At this point, o is not null, but foo is null
>
> Deserialization succeeds. The problem is that the deserialized object is a
> version 1 object. During deserialization, .NET finds the old version of
> the library in the GAC, even though I have compiled against version 2.0.
> The deserialized object is essentially unusable. The cast from object to
> Foo returns a null object, since the returned object is not a 2.0 Foo. The
> modules view in the debugger shows that both versions of the library are
> loaded.
>
> If I remove the 1.0 version of the library from the GAC, deserialization
> correctly returns a 2.0 Foo object. Is there a way to make this work that
> doesn't involve removing the old library from the GAC? Having the old
> version available solves a different set of problems for us.
>
>
> Here is a complete set of steps + code to reproduce
>
> 1- Create a simple, serializable class
>
> //---------- MyLib.cs-----------
> using System;
> using System.Collections.Generic;
> using System.Reflection;
>
> [assembly: AssemblyTitle("MyLib")]
> [assembly: AssemblyVersion("1.0.0.0")]
>
> namespace MyLib
> {
>
> [Serializable]
> public class Foo
> {
> public Foo()
> {
> for(int i=0;i<10; ++i)
> {
> Values.Add(i);
> }
> }
>
> public List<int> Values = new List<int>();
> }
> }
>
>
> 2- Compile MyLib.cs into a strongly named library, and add it to the GAC:
>
> > sn -k key.snk
> > csc /t:library /keyfile:key.snk MyLib.cs
> > gacutil /i MyLib.dll
>
>
> 3- Create an app that serializes an instance of Foo from version 1.0 of
> the library. Compile and execute
>
> //-------Create.cs-------
> using System;
> using System.Collections.Generic;
> using System.IO;
> using System.Runtime.Serialization;
> using System.Runtime.Serialization.Formatters;
> using System.Runtime.Serialization.Formatters.Binary;
>
> using MyLib;
>
> static public class Program
> {
> [STAThread]
> public static void Main()
> {
> Foo foo = new Foo();
>
> BinaryFormatter formatter = new BinaryFormatter();
> formatter.AssemblyFormat = FormatterAssemblyStyle.Simple;
>
> using(FileStream stream = File.Create("foo.bin"))
> {
> formatter.Serialize(stream, foo);
> }
> }
> }
>
> > csc /r:MyLib.dll Create.cs
> > Create.exe
>
>
> 4- Add a new field to Foo, bump the version, rebuild, and install the new
> version into the GAC
>
> //---------- MyLib.cs-----------
> ...<snip>
> [assembly: AssemblyVersion("2.0.0.0")]
>
> ...<snip>
>
> public class Foo
> {
> ... <snip>
> public string Text = "hello";
> }
>
> > csc /t:library /keyfile:key.snk MyLib.cs
> > gacutil /i MyLib.dll
>
> 5- Create an app that tries to load the file that was serialized from
> version 1.0 of the DLL. Compile and execute
>
> //-------Load.cs-------
> using System;
> using System.Collections.Generic;
> using System.IO;
> using System.Runtime.Serialization;
> using System.Runtime.Serialization.Formatters;
> using System.Runtime.Serialization.Formatters.Binary;
>
> using MyLib;
>
> static public class Program
> {
> [STAThread]
> public static void Main()
> {
> object o = null;
> Foo foo = null;
>
> BinaryFormatter formatter = new BinaryFormatter();
> formatter.AssemblyFormat = FormatterAssemblyStyle.Simple;
>
> using(FileStream stream = File.OpenRead("foo.bin"))
> {
> o = formatter.Deserialize(stream);
> }
>
> Console.WriteLine(o.GetType().AssemblyQualifiedName);
>
> foo = o as Foo;
> if(foo == null)
> Console.WriteLine("foo is null");
> else
> Console.WriteLine("foo is not null. Loaded correctly");
> }
> }
>
> > csc /r:MyLib.dll Load.cs
> > Load.exe
>
> The output from Load.exe is
>
> MyLib.Foo, MyLib, Version=1.0.0.0, Culture=neutral,
> PublicKeyToken=0b5ef2fdd6494a50
>
> foo is null
>
> If I remove the 1.0 version of MyLib from the GAC, deserialization
> succeeds. The output is:
>
> MyLib.Foo, MyLib, Version=2.0.0.0, Culture=neutral,
> PublicKeyToken=0b5ef2fdd6494a50
> foo is not null. Loaded correctly
>
> H^2
>
>