Add a single entry gate for dispose

This ensures we only call dispose once and that anything other method throws an `ObjectDisposedMethod` when the cache is disposed.

Handling this is trickier than expected. For example, we can't just move `isdisposed` up higher because the `Dispose` method calls other methods that check `isdisposed`. I tried passing in a `disposing`.

Another option is to take the guts of these methods, put them in private methods, and call the same methods from `Dispose` and from the public methods.

I couldn't get all the tests to pass in any situation. :( It would be nice to have more complete test coverage here.