Consider the following scenario:
- A NuGet package contains two versions of an assembly, one for .NET 3.5 (in lib/net35) and one for .NET 4.0 (in lib/net40). Both are named SomeInterfaces.dll and have version 1.0.0.0, but the strong names for the two assemblies have different
publicKeyToken
values. - An application named CoolProgram.exe exists, and exposes extensibility features (e.g. via MEF)
- Company A develops an extension AExtension.dll and references the .NET 3.5 version of SomeInterfaces.dll.
- Company B develops an extension BExtension.dll and references the .NET 4.0 version of SomeInterfaces.dll.
- One of the following is provided:
- The extensions AExtension.dll and BExtension.dll are placed in the same folder as CoolProgram.exe, and the two copies of SomeInterfaces.dll are placed in the GAC.
- The application adds the paths where extensions are installed to the CLR binding path. For example, AExtension.dll and SomeInterfaces.dll (.NET 3.5) could be placed in the directory extensions/A, and BExtension.dll and SomeInterfaces.dll could be placed in the directory extensions/B; both of these two directories are placed in the binding path of the application CoolProgram.exe.
Questions:
In situation 5.1:
- Will CoolProgram.exe be able to load AExtension.dll and BExtension.dll without any problems due to them referencing two assemblies that only differ by their
publicKeyToken
? - Does the order in which the extensions are loaded make a difference?
- Does the answer change if CoolProgram.exe does not have a strong name, but both AExtension.dll and BExtension.dll do have strong names?
- Will CoolProgram.exe be able to load AExtension.dll and BExtension.dll without any problems due to them referencing two assemblies that only differ by their
The same as question 1, but applied to situation 5.2.
Optional Background Information:
If two assemblies are compatible at runtime; i.e. they expose the same public API and only differ in their implementation (e.g. one restricted to .NET 3.5 for the implementation and one using .NET 4.0 types in the private implementation code), then users will not face assembly binding problems in extensible applications even if the two assemblies have exactly the same strong name. This is not the case for situations where the public API differs in some way.
One solution to the case where the public API differs is to use separate names for each version of an assembly. This could lead to cases like the following for the ANTLR 4 Runtime:
- Antlr4.Runtime.net20.dll
- Antlr4.Runtime.net30.dll
- Antlr4.Runtime.net35.dll
- Antlr4.Runtime.net40.dll
- Antlr4.Runtime.net45.dll
- Antlr4.Runtime.portable_net40.dll
- Antlr4.Runtime.portable_net45.dll
- Antlr4.Runtime.netcore45.dll
The documentation associated with the project could be simplified if all the assemblies could be named Antlr4.Runtime.dll. In the case where users know they are working in an environment where multiple vendors could be providing code that references assemblies with different target frameworks but otherwise the same version, steps could be taken to ensure their assemblies can be located at runtime. A concrete example would be two Visual Studio extensions using ANTLR for syntax highlighting, one targeting Visual Studio 2010+ (using .NET 4.0), and one targeting Visual Studio 2012+ (using .NET 4.5). The [ProvideBindingPath]
and/or [ProvideCodeBase]
attribute could be used to provide exactly the functionality described in situation 5.2.