views:

396

answers:

3

I would like to create a class that compiles into a single DLL. This DLL would add functionality to an existing product.

To make this work, the custom class references DLLs contained in the underlying product. These references are needed to compile.

Everything works fine here and the custom class compiles. I can drop the DLL produced into the product and everything works fine.

However, this product has several versions (minor versions, service packs). I would like to distribute this DLL to others but I'm finding the DLL must match perfectly the version of the product. If there isn't a perfect match, then the following error occurs:

Could not load file or assembly 'Product.Web.UI, Version=3.6.1920.2, Culture=neutral, PublicKeyToken=dfeaee0e3978ac79' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

How do I produce a DLL that isn't picky about the version reference?

+2  A: 

I don't yet have an answer to my question, but I'll use this answer to log breadcrumbs I found while searching for a solution.

I found a somewhat related question on StackOverflow:

Compile a version agnostic .DLL in .NET (Using Manifests?)

I have no ability to modify the underlying product however, so the answer does not work for me.


Updated:

I emailed someone much smarter than me and here was the reply:

When you reference strong-named assembly, by default Visual Studio adds full reference to the referenced assembly. That means it includes the name of the assembly, the exact version, the culture and the public key token. If any of this information don't match the described exception is thrown.

Removing the strong-names of our assemblies is simply not an option. I won't go in details why, but you can do some research in MSDN.

So, you have two options to workaround building against every version of the assemblies you are referencing.

  1. You could do partial referencing. See this article: http://msdn.microsoft.com/en-us/library/0a7zy9z5(VS.71).aspx.
  2. You can declare compatible versions with binding redirection in the web.config. See this article: http://msdn.microsoft.com/en-us/library/433ysdt1.aspx.

In general the second approach is recommended because: 1. You cannot use partial reference to assemblies in the Global Assembly cache, meaning your control will throw the same exception if assemblies are in the GAC. 2. You explicitly state compatible versions.

Gabe
A: 

Hi there,

In VisualStudio - have you tried right clicking on the referenced assembly (dll) and then selected properties and set "requires specific version" (or so) yet? That may solve your issue.

Andreas

Yep, tried it. My understanding is this setting only applies at compile-time. Meaning, during build the compiler isn't picky about the version of the DLL it finds.However, for the resulting DLL, those non-specific DLL references will be turned into strongly-named assembly references (complete with version number) based on the the DLL that was used to compile.
Gabe
A: 

This is an excellent solution. It solved a similar problem for me.

http://stackoverflow.com/questions/277817/compile-a-version-agnostic-dll-in-net-using-manifests/284462#284462

In case that link ever dies, the key is to handle the AppDomain.CurrentDomain.AssemblyResolve event like below. The event fires any time an assembly binding fails, so you can resolve it yourself, fixing version conflicts.

using System.Reflection;

static Program()
{
    AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs e)
    {
        AssemblyName requestedName = new AssemblyName(e.Name);

        if (requestedName.Name == "Office11Wrapper")
        {
            // Put code here to load whatever version of the assembly you actually have

            return Assembly.LoadFile("Office11Wrapper.DLL");
        }
        else
        {
            return null;
        }
    }
}
Yoenhofen