At least for v2 and earlier, mscorlib.dll is a special case. That causes it and its types to be loaded differently from other assemblies.
Loading Mscorlib.dll Without a Path
It and the execution engine are so closely integrated that it's required that they match each other. So, once a version of the CLR is chosen, the version of mscorlib is also chosen automatically. That means that, when late binding (Assembly.Load(), etc.) for it without a path, the 'official' mscorlib Assembly will always be returned - regardless of the version that was requested. The same thing goes for loading by static reference to it.
This doesn't mean that it's okay to give an incomplete or incorrect reference for it! If/when mscorlib.dll is factored away from the execution engine, it won't be such a special case and bad references will start to fail to load.
Reflecting On Another Mscorlib.dll
It's possible to load another mscorlib.dll if it's loaded by path. But, it's not possible to load its types, due to optimizations done by the CLR's execution engine. (Same goes for ReflectionOnlyLoadFrom() on another mscorlib.dll.) This means that even if you rename the mscorlib.dll that you want to reflect over, it may be loaded, but its types will still be unloadable. So, the options for working around this are:
- Reflect on the 'official' mscorlib.dll. You could change the version of the CLR that your app loads in order to reflect on the desired mscorlib version.
- Use the unmanaged metadata API to get the desired info.
- Create an asmmeta file for the desired mscorlib.dll and parse it at runtime.