Using interfaces and base classes in different assembly using vsewss 1.3
In a previous post, I mentioned that there are difficulties with using the Visual Studio extensions for Windows SharePoint Services (VSeWSS) in combination with interfaces. It turns out that this problem is not just limited to using base classes, but also to using base classes in different assemblies.
Just a small recap of the problem i was facing:
I had placed an interface in a different assembly than the implementation. For example, we had created an interface for doing logging, the ILogger interface and had created a basic implementation for this interface. Our own reusable code was using this ILogger, however, we wanted users of our library to be able to create and plug in their own logger. To do that, they have to derrive from the ILogger interface. However, as soon as you would do this, your project wouldn’t package anymore.
While packaging, i got the following error:
Error 1 VSeWSS Service Error: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
Although I don’t have a true solution for this problem, I do have a workaround. If the DLL that contains the baseclass is in the GAC, then VSeWSS can find it.
I found that, if you placed the DLL’s that have the base classes and interfaces in the GAC, then VSeWSS can find them. It took me a while to find this out because if you run into this error and then add the DLL into the GAC, then you have to perform an IISReset before VSeWSS finds out that you have added it to the GAC.
I decided to add a post build script to remove and add my files to the GAC. One other challenge I ran into was, that GACUTIL.EXE is not in the same location on every machine. And there is no, easy to use environment variable to find it. So I created a small .BAT file to help me with this.
This is the content of the RegisterInGAC batch file:
set gacutil=%programfiles%\Microsoft SDKs\Windows\v6.0A\Bin\gacutil.exe
echo *** RegisterInGac.bat %1 %2 echo * Trying to find GacUtil.exe:
if not exist "%gacutil%" echo * Could not find GACUtil at: %gacutil% if not exist "%gacutil%" set gacutil=%ProgramW6432%\Microsoft SDKs\Windows\v6.0A\Bin\gacutil.exe if not exist "%gacutil%" echo * Could not find GACUtil at: %gacutil% if not exist "%gacutil%" goto error
echo * Using gacutil.exe from %gacutil%
call "%gacutil%" %1 %2 goto done
:error echo * Warning: Could not (un)register %2 in the gac.
You can see that it’s trying to find the GACUtil from several locations and it’s telling you which one it’s using.
And to get it to work, I placed this script in the Post build event:
My .BAT file is located a couple of levels up in my source tree, so I have to find it there.
Nice side-effect of this approach
I’ve found that there is a nice side-effect to using this approach.
Our packages are also placing some DLL’s into the GAC. However, because assemblies in the GAC take precedence over assemblies on the filesystem, this can cause issues when running unit tests. The unit test will not use the latest version (that you have just built), but it will use an older version that’s still in the GAC. By using this approach, you basically make sure that the version in the GAC is always the latest version.
Hope this helps.