As you already mentioned, if the a.dll has reference to b.dll, then you do not need to "NETLOAD" b.dll, because when a.dll is netloaded, b.dll is also loaded because of the reference.
However, as you requested, you could load b.dll using System.Reflection whenever needed: Assembly.Load()/LoadFile()/LoadFrom() (there are subltle differences among the 3 loading methods that you need to pay attention). Assembly loaded this way is the same as loaded by Acad's "NETLOAD" command (and the IExtensionApplication will run upon loading). Better yet, before you load the DLL assembly, you not only make sure the dll is in the .NET loading location according to .NET loading poll-mechnism; but also check if the assembly has already been loaded, to which you can use AppDomain.CurrentDomain.GetAssemblies() to find out loaded .NET assemblies (by its fully qualified name/version...).
Fortunately, the Autodesk.AutoCAD.Runtime.ExtensionLoader class (available since Acad2013?) has Load()/IsLoaded to do exactly the things aforementioned in more simplfied way.
HTH.