3

Let's say I got projects A, B and C. Project A references projects B (v. 2.0.0.0) and C (v. 3.0.0.0). Project B references only project C (v. 1.0.0.0). We got a conflict on our hands, since project A and B depend on different assembly versions of project C. In .NET framework we solve this issue using binding redirects. In Project A's app.config file (being the main project) we add:

<dependentAssembly>
    <assemblyIdentity name="C"  
                      publicKeyToken="<somePublicKeyToken>"  
                      culture="en-us" />  

    <bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />  
</dependentAssembly>

I believe that binding redirects are no longer a thing in .NET Core and .NET 5 forward. Instead of referencing an assembly, we reference a NuGet package or a project. My question is: how is this issue solved in newer version of .NET? Why were binding redirects a thing in the first place? Hope my question makes sense.

vladek
  • 577
  • 1
  • 4
  • 17
  • 1
    "Instead of referencing an assembly, we reference a NuGet package or a project. " - nah, the `csc` compiler still generates your `.exe`/`.dll` files with good ol' fashioned assembly-references inside of it. And you can still do manual assembly references from .NET Core / .NET 5+ `.csproj` projects too - it's just kinda buried. – Dai Mar 23 '22 at 10:48
  • Interesting, didn't know that, thanks for pointing out. I tried to find something on the matter but I probably just haven't been googling it properly. – vladek Mar 23 '22 at 10:55

1 Answers1

2

As others pointed out, a package version is a completely different thing from an assembly version. In the end, your build still refers to an assembly. It just happens that the assembly was delivered to your build environment in a package.

You are correct that .Net 5+ does not (by default) require that the assembly version used at runtime match the assembly version used at build time.

I'll speculate that the early design of .Net was attempting to address the "DLL Hell" problem. By formalizing the notion of the DLL version (by placing the version in the metadata of the assembly), an application could verify that it was getting exactly the version that it expected to get, and so would have dependable behavior. Still, you wanted to be able to use a newer version at times, without rebuilding the referring application, so <bindingRedirect was provided.

.Net Core recognizes that it wasn't a successful design. The new approach a) ignores strong naming: it doesn't affect behavior. b) defaults to allowing any version at runtime, and c) provides a new mechanism for enforcing version policy: AssemblyLoadContext

Elroy Flynn
  • 3,032
  • 1
  • 24
  • 33
  • "You are correct that .Net 5+ does not (by default) require that the assembly version used at runtime match the assembly version used at build time." Can you name a source for that? I have just read https://stackoverflow.com/a/802038 and found that this answer obviously applies to .NET Framework, but not to .NET 5+, see my comment below it. Is this correct? – Tobias Knauss Jul 07 '22 at 22:03
  • 2
    It's hard to find definitive docs (hard to prove a negative?) but https://learn.microsoft.com/en-us/dotnet/standard/library-guidance/versioning says "In .NET Core, assembly loading is more relaxed. The .NET Core runtime automatically loads assemblies with a higher version at run time." The new behavior can also be assumed from the docs on assembly loading in .net (core) such as the one I referenced before, and links within it. They say nothing about version matching, while articles on .net framework have a lot to say about it, and . – Elroy Flynn Jul 08 '22 at 23:53