Improve duplicate assembly resolving (#89958)
`GetAssembly` opens a new assembly and stream every time it is called and keeps them open for the duration of the run.
`RootAssemblyFile.LoadAssemblyFile` sort of handled an already loaded assembly, but it left a new `AssemblyDefinition` instance and `MemoryStream` open every time it happened.
`CacheAssembly` was easy to make a mistake with. Forget to do the delicate dance that `RootAssemblyFile.LoadAssemblyFile` goes to already loaded assemblies and you can easily overwrite an already cached assembly. Guard against mistakes rather than quitely overwriting the assembly that was already cached.
Why force callers of `CacheAssembly` to check if something is cached already? Handle that case internally.
With these changes the logic in `RootAssemblyFile.LoadAssemblyFile` is simplified and an extra copy of the assembly is no longer left open in the scenario where an assembly is specified multiple times.