assembly binding to redirect to a different assebly file
-
Thursday, May 10, 2012 9:43 AM
Hello,
i transfered a class to a different assembly but kept the same namespaces. My application is deserializing a file that contains type references to this class and now i get exceptions because it is looking for the old assebly. So i created a SerializationBinder decendant to handle that, but although the BindToType method is called for other types that have also been moved, it is never called for the class type that is causing the exception.
The next thing i did was to add a CodeBase reference to the applications config file to point to new assebly that contais that type but still i get the same excpetion that the old assembly file cannot be located
My original class was structured like this:
Assembly file MyLib.Classes.dll (version 1.0.0.0)
Namespace MyLib.Classes
Public Class TestClass
and then like this:
Assembly file MyLib.dll (version 1.0.0.1)
Namespace MyLib.Classes
Public Class TestClass
my serializationbinder looks like this:
Public Class CustomSerializationBinder Inherits Runtime.Serialization.SerializationBinder Public Overrides Function BindToType(assemblyName As String, typeName As String) As System.Type assemblyName = assemblyName.Replace("MyLib.Classes, Version=1.0.0.0", "MyLib Version=1.0.0.1") typeName = assemblyName.Replace("MyLib.Classes, Version=1.0.0.0", "MyLib Version=1.0.0.1") Return Type.GetType(String.Format("{0}, {1}", typeName, assemblyName)) End Function End Classthe deserialization code is like this:
Dim Bytes() As Byte = value Using Stream As New IO.MemoryStream(Bytes) With {.Position = 0} Dim b As New Runtime.Serialization.Formatters.Binary.BinaryFormatter() With {.Binder = New CustomSerializationBinder()} Return b.Deserialize(Stream) End Usingand finally my configuration file looks like this:
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="MyLib.Classes" publicKeyToken="e9a4f5adb9bd741c" culture="neutral" />
<CodeBase Version="1.0.0.1" href="file:///c:\temp\MyLib.dll" />
</dependentAssembly>
</assemblyBinding>
</runtime>
MyLib.Classes.dll and MyLib.dll are strong name assemblies.
Upon deserialization i get the following exception:
Message: Could not load file or assembly 'MyLib.Classes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e9a4f5adb9bd741c' or one of its dependencies. The system cannot find the file specified.
Stack Trace: at System.Reflection.Assembly._GetType(String name, Boolean throwOnError, Boolean ignoreCase)
at System.UnitySerializationHolder.GetRealObject(StreamingContext context)
at System.Runtime.Serialization.ObjectManager.ResolveObjectReference(ObjectHolder holder)
at System.Runtime.Serialization.ObjectManager.DoFixups()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)
at .......Fusion.Log:=== Pre-bind state information ===
LOG: User = PC2\Theodore
LOG: DisplayName = MyLib.Classes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e9a4f5adb9bd741c
(Fully-specified)
LOG: Appbase = file:///D:/.../MyApp/bin/x86/Debug/
LOG: Initial PrivatePath = NULL
Calling assembly : (Unknown)
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: D:\...\MyApp\bin\x86\Debug\MyApp.vshost.exe.Config
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v2.0.50727\config\machine.config.
LOG: Post-policy reference: MyLib.Classes, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e9a4f5adb9bd741c
LOG: Attempting download of new URL file:///D:/.../MyApp/bin/x86/Debug/MyLib.Classes.DLL.
LOG: Attempting download of new URL file:///D:/.../MyApp/bin/x86/Debug/MyLib.Classes.DLL/MyLib.Classes.DLL.
LOG: Attempting download of new URL file:///D:/.../MyApp/bin/x86/Debug/MyLib.Classes.EXE.
LOG: Attempting download of new URL file:///D:/.../MyApp/bin/x86/Debug/MyLib.Classes.EXE/MyLib.Classes.EXE.Is there a way around this problem?
Regards,
Theodore
Theo
All Replies
-
Thursday, May 10, 2012 3:45 PM
I solved this problem on own and i share it for the benefit of everyone who cares to know.
I added a handler to the application domain's AssemblyResolve event and there i loaded the new assembly.
AddHandler AppDomain.CurrentDomain.AssemblyResolve, AddressOf AssemblyResolver Private Function AssemblyResolver(ByVal source As Object, ByVal e As ResolveEventArgs) As Reflection.Assembly If e.Name.Contains("MyLib.Classes") Then Return Reflection.Assembly.Load("MyLib, Version=1.0.0.1, Culture=neutral, PublicKeyToken=e9a4f5adb9bd741c") Else : Return Nothing 'Reflection.Assembly.Load(e.Name) End If End Function
Theo
- Marked As Answer by theodorep Thursday, May 10, 2012 3:45 PM

