Search code examples
.netdlldynamic-loading

How to manage run-time loaded dll versions?


A bit of background:

I have a library project A, which contains a lot of data and some managed DLLs. This project has its own installer (due to its size) and can be installed independently.

Then I have some other projects which can provide extra features when they detect that project A is also installed.

Setup: I created an Interface.dll which contains intefaces that are implemented by project A. All other projects include this DLL so I can load project A at runtime and cast it to specific interface.

The problem occurs with versioning. Sometimes some projects will include newer version of Interface.dll while installed project A has dependency on an older one. When this happens my cast no longer works.

I am considering some possibilities:

  1. Ditch interface.dll and load everything dynamically.
  2. Some version detection and inform user to update his version of project A.
  3. Use some other means of communication (e.g. command line)

Solution

  • Presumably the interfaces defined in interfaces.dll and implemented by project A haven't changed? Maybe the other projects have just added new interfaces.

    You might have a plain old .NET DLL versioning issue here. Project A (A.exe?) is compiled against interfaces.dll version 1.0.0.0, and this information is stored in A.exe's metadata. When you update interfaces.dll to 1.0.0.1, A.exe can't load it. If the new DLL is backwards compatible (which it really must be for your casts to work) then you can supply a policy file that tells the runtime loader about this compatibility. For example:

    <?xml version ="1.0"?>
    <configuration>
    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <dependentAssembly>
            <assemblyIdentity name="interfaces" culture="neutral" publicKeyToken="null"/>
            <bindingRedirect oldVersion="1.0.0.0-1.0.0.1" newVersion="1.0.0.1"/>
        </dependentAssembly>
        </assemblyBinding>
    </runtime>
    </configuration>
    

    This tells the loader that if an assembly tries to load any version of interfaces.dll between 1.0.0.0 and 1.0.0.1, then version 1.0.0.1 is acceptable. Name this file after your DLL, using a standard pattern: policy.1.0.interfaces.xml. Then put it in the same directory as your A.exe (I think.)

    Alternatively, if you haven't changed the version number of interfaces.dll (which you really should) then you might have a different problem. If you've got two assemblies whose identities are the same but they're not actually the same assemblies, then once the runtime loader has loaded one of them it will never load the second. There are more details, but since I reckon this is unlikely to be your problem I won't go into them right now.