using assemblies with different verions

  • Thread starter Thread starter bryan
  • Start date Start date
B

bryan

I have an C# windows app called Test.Exe. It is built with a reference to a
strongly named assembly called Base.dll, with a specific version and public
/ private key set. The version of Base.dll that Test.exe refers to is in the
same directory as Text.exe.

This application wants to load a strongly named assembly called Derived.dll
(in a separate directory), which was also built with a reference to a
(potentially different version of the) strongly named assembly of Base.dll.
The version of Base.DLL that Derived.dll refers to is located in the same
directory as Derived.DLL.

The application loads the Derived.dll assembly with a complete specification
(name, version and public key token) and uses
System.Reflection.Assembly.CreateInstance to create an instance of a class
from the assembly. If the versions of the Base.dll assembly are the same
(same build) then the instance is created successfully.

However, when the versions of Base.dll are different we get an error. The
assembly object is successfully loaded, but when used to call CreateInstance
of a type defined in Derived.dll, the
System.Reflection.Assembly.CreateInstance method returns null.

To test that the different version of Base.dll were the issue, we built
Test.EXE from the same version as Derived.dll was built from, and when that
version is executed, the system performs correctly.

What do we do to get implicitly included assemblies to use the specific
version of the assemblies that they refer to - and cause a load of a new
version if the one that is currently loaded is the correct name, but
incorrect version?
 
One solution is to use binding redirects to force the runtime to load and
use a specific version of base.dll even though other assemblies
(derived.dll) has a reference to an earlier/different version of base.dll.
You can put these into the app.config file.
 
Thanks, but I think I was unclear.

The application loads with the correct version of Base.dll for it. Then, at
a later time the application loads the Derived.dll assembly (like a Plug In
interface). When the Derived.dll is loaded, apparently the incorrect
version of Base.dll that was loaded for the application is enough to satisfy
the requirement for the references in Derived.dll and so the correct version
is not ALSO loaded.

I do not explicitly load the Base.dll assembly in either case.
 
This is exactly the situation that binding redirect addresses. You cannot
have two different versions of the same assembly identity (same name and
strong name) loaded into the same appdomain at the same time; the runtime
does not allow that.
You can load the Derived.dll into a second appdomain and avoid the binding
issue; you will then you will need to use remoting to communicate between
the application and the Derived.dll (the way many plugin architectures
work).
If you want to load them both into the same appdomain then either they must
both be built against the same version of the base.dll, or you must use
binding redirects to force all implicit references from derived.dll to use
the same version of base.dll that the application uses - this is a
reasonable strategy IMO.

FYI: this will avoid typecast exceptions that would otherwise occur when the
application attempts to access a method or property defined in a type in
base.dll and contained in an instance of Derived. The reason is that the
Application will use a definition of base.dll (e.g v1.2.3.4) but the derived
instance is using base .dll v2.3.4.5. The runtime treats these as two
completely different assemblies, thus the types defined in each are not
equivalent - you cannot convert from one to the other.

When you share types defined in an assembly between two or more other
assemblies then all references to the shared type must be directed to the
same assembly; either by binding directly to the same assembly, or by
redirecting the references to the same assembly.
 
Back
Top