MPB are a dead concept if you are using the SRP batcher. They are not compatible at all with it and generally work against all of the optimizations that it makes in the first place. The only example I’ve seen of using them is for modifying per-object properties during edit-time. There would then be some conditional compilation and/or use of Application.isPlaying to instead use one of the below methods at runtime. The reason for this is simply because creating new materials at edit-time comes with its own set of challenges involving how and when to properly clean up assets and memory use.
As for runtime: You’re best options are either to dynamically create the new materials as needed, usually using some kind of caching system (similar to how you describe with the dictionary) or to use the new Render Shader User Value. In earlier versions of Unity than this is was also possible to re-purpose some of the built-in renderer values such as probe indices as long as the shader wasn’t using them. Here’s the official post detailing all of this information.
The RSUV is absolutely something I’ve been dying to have for years but in general, it’s never been much of an issue to just generate new materials on the fly for runtime anyway. The performance overhead for multiple materials is negligible in 99.9% of all cases.