Esempio n. 1
0
        protected virtual TResult VisitCallSite(ServiceCallSite callSite, TArgument argument)
        {
            if (!_stackGuard.TryEnterOnCurrentStack())
            {
                return(_stackGuard.RunOnEmptyStack((c, a) => VisitCallSite(c, a), callSite, argument));
            }

            switch (callSite.Cache.Location)
            {
            case CallSiteResultCacheLocation.Root:
                return(VisitRootCache(callSite, argument));

            case CallSiteResultCacheLocation.Scope:
                return(VisitScopeCache(callSite, argument));

            case CallSiteResultCacheLocation.Dispose:
                return(VisitDisposeCache(callSite, argument));

            case CallSiteResultCacheLocation.None:
                return(VisitNoCache(callSite, argument));

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
Esempio n. 2
0
        private ServiceCallSite?CreateCallSite(Type serviceType, CallSiteChain callSiteChain)
        {
            if (!_stackGuard.TryEnterOnCurrentStack())
            {
                return(_stackGuard.RunOnEmptyStack((type, chain) => CreateCallSite(type, chain), serviceType, callSiteChain));
            }

            // We need to lock the resolution process for a single service type at a time:
            // Consider the following:
            // C -> D -> A
            // E -> D -> A
            // Resolving C and E in parallel means that they will be modifying the callsite cache concurrently
            // to add the entry for C and E, but the resolution of D and A is synchronized
            // to make sure C and E both reference the same instance of the callsite.

            // This is to make sure we can safely store singleton values on the callsites themselves

            var callsiteLock = _callSiteLocks.GetOrAdd(serviceType, static _ => new object());

            lock (callsiteLock)
            {
                callSiteChain.CheckCircularDependency(serviceType);

                ServiceCallSite?callSite = TryCreateExact(serviceType, callSiteChain) ??
                                           TryCreateOpenGeneric(serviceType, callSiteChain) ??
                                           TryCreateEnumerable(serviceType, callSiteChain);

                return(callSite);
            }
        }