This change to ModelBinderFactory makes the caching much more aggressive,
by caching all non-root binders. There's some trickiness here around
making sure we have the right behavior when all providers return null. See
the tests and comments.
I also kept the change I made for a temporary workaround to use a
dictionary rather than a "stack" for cycle breaking. This seems like an
overall improvement in clarity.