The Problem:
We are trying to move an application from .NET Framework to .NET 8. The application needs to consume some third-party .NET Framework assemblies, one of which uses the Framework-only class System.Security.Cryptography.ProtectedMemory.
I'm wondering if there's any way for me to provide an implementation of that class that I can cause to get picked up when the third-party assembly tries to load the .NET Framework version, for which it won't find a type forward from .NET 8.
This sounds horribly insecure to me, so I suspect it's not possible. But we're in a real pickle if it can't be done.
While I didn't find any way to achieve type forwarding at runtime (probably for good reason), I did come across a GitHub issue where a developer was trying to replace an inbox DLL with a modified build of it, just for his application.
To sum up the GitHub conversation, you can override a system DLL in your .NET application by creating your own version with the same name and public key but a higher version number. You then include it in your C# project as an assembly reference or NuGet package. This adds your custom DLL to the app's .deps.json file, causing it to be loaded in preference to the lower-versioned DLL that ships with .NET.
In my case, I wanted to add two missing type forwards to System.Security.dll. Rather than clone the entire .NET runtime repo to build a custom version from source, I used dnlib to modify the inbox assembly directly. I have a GitHub repo with a full demonstration of this technique and how to incorporate it into a working .NET 8 app, but here's the code for the app that creates the modified shim DLL:
I didn't have to sign the DLL because the original already had a public key, but if you need to rebuild a .NET DLL, you can use public signing.
The missing puzzle piece for me is getting this all to work in a C++/CLI application, but that probably isn't relevant for most readers of this answer.