Montag, 4. August 2008

Satellite assemblies do not work with codeBase attribute

The codeBase attribute in the <dependentAssembly> tag used in application configuration files is a nice way to specify the location of some assemblies which your application uses.

Why should you need that, by the way? For us, it's because we want to have the possibility to load different versions of the same assembly at the same time. That is needed because the application is big and not all clients of the assembly can immediately be changed if a new version is made (with interface changes). Then, the different versions are put into different subdirectories, and with the codeBase attribute, the runtime can find them.

OK, I hear you say, why not use the GAC? It seems specifically made for that purpose. But the GAC has some other problems of its own (I may blog about that in another post); application configuration files are much easier for us.

Now I've discovered that satellite assemblies (which are used to localize .NET programs) are just not found with this mechanism. E.g., if you've got an assembly 'MyAssembly' with version 1.0.0.0, you put it into a subdirectory 'MyAssembly/1.0.0.0' and point the codeBase attribute there. But if you need a German version, you can't put the satellite assembly (MyAssembly.resources.dll) into the directory 'MyAssembly/1.0.0.0/de'; it won't be found. You've got to put it directly into the subdirectory 'de' of your application, which of course won't work with several different versions. There's also no way to specify a codeBase for the satellite assembly in the configuration file. It seems there is no way to use codeBase in satellite assemblies together at all. At least I've found none.

We don't actually have a localized assembly in different versions yet (those assemblies which are used by many clients do normally not need to be localized), but the situation could arise in the future. Then we'll probably have to revert to putting the version into the file name, as it is often done with native libraries. Yuck.

BTW, using the <probing> element to specify a private path works, but doesn't help if you want to have different versions in parallel.

I assume the reason for all this is that satellite assemblies are internally loaded using the same probing mechanism as normal assemblies. I.e., they are not searched relative to the assembly they belong to. Too bad.

Labels: