Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to have version-independent DLL references in a class?

Tags:

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?

like image 796
Gabe Sumner Avatar asked May 14 '09 00:05

Gabe Sumner


People also ask

What is the difference between project reference and DLL reference?

Well, project references are helpful when you are building and testing in both debug and release mode. If you directly add a DLL then you are locked into whatever that particular DLL was built as. The project reference allows this to be a build time decision. This is correct what you are saying.

How do I change the reference version in Visual Studio?

Open the project in Visual Studio. Right-click on the project's References folder and select Add Reference to open the Add Reference dialog box. Locate the new assembly version in the Add Reference dialog for each Infragistics assembly listed in your References folder.


2 Answers

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

Compile a version agnostic DLL in .NET

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;
        }
    }
}
like image 135
Yoenhofen Avatar answered Oct 12 '22 22:10

Yoenhofen


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.

like image 29
Gabe Sumner Avatar answered Oct 12 '22 21:10

Gabe Sumner