Decent implementation, but a few nits.
Definition of scope (singleton, etc.) should be handled on the registration side. Handling it on the resolution side pretty much lets anyone ignore the scope type at will and grab whatever they want, which pretty much defeats the purpose of having singletons.
Service consumers shouldn't know or care if the object is scoped or not. They simply ask for what they need and get it.
Second biggest issue is lack of thread management around registration and scope caches. In multi-threaded environments it's way to easy to have contention issues around read/writes to those structures, which can cause application crashes.
But keep in mind if you do locking that you need reclusive locks, since, as mentioned, making A can make a B which makes a C.
See Factory for some examples of this.