public object Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope)
 {
     return(VisitCallSite(callSite, new RuntimeResolverContext
     {
         Scope = scope
     }));
 }
        protected override object VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
        {
            if (callSite.Value is object value)
            {
                // Value already calculated, return it directly
                return(value);
            }

            var lockType = RuntimeResolverLock.Root;
            ServiceProviderEngineScope serviceProviderEngine = context.Scope.Engine.Root;

            lock (callSite)
            {
                // Lock the callsite and check if another thread already cached the value
                if (callSite.Value is object resolved)
                {
                    return(resolved);
                }

                resolved = VisitCallSiteMain(callSite, new RuntimeResolverContext
                {
                    Scope         = serviceProviderEngine,
                    AcquiredLocks = context.AcquiredLocks | lockType
                });
                serviceProviderEngine.CaptureDisposable(resolved);
                callSite.Value = resolved;
                return(resolved);
            }
        }
Beispiel #3
0
        internal object GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
        {
            var realizedService = RealizedServices.GetOrAdd(serviceType, _createServiceAccessor);

            _callback?.OnResolve(serviceType, serviceProviderEngineScope);
            return(realizedService.Invoke(serviceProviderEngineScope));
        }
 public ExpressionResolverBuilder(CallSiteRuntimeResolver runtimeResolver, IServiceScopeFactory serviceScopeFactory, ServiceProviderEngineScope rootScope) :
     base()
 {
     _runtimeResolver     = runtimeResolver ?? throw new ArgumentNullException(nameof(runtimeResolver));
     _serviceScopeFactory = serviceScopeFactory;
     _rootScope           = rootScope;
 }
Beispiel #5
0
        public void DoubleDisposeWorks()
        {
            var engine = new FakeEngine();
            var serviceProviderEngineScope = new ServiceProviderEngineScope(engine);

            serviceProviderEngineScope.ResolvedServices.Add(new ServiceCacheKey(typeof(IFakeService), 0), null);
            serviceProviderEngineScope.Dispose();
            serviceProviderEngineScope.Dispose();
        }
        public void Dispose_DoesntClearResolvedServices()
        {
            var serviceProviderEngineScope = new ServiceProviderEngineScope(null);

            serviceProviderEngineScope.ResolvedServices.Add(new ServiceCacheKey(typeof(IFakeService), 0), null);
            serviceProviderEngineScope.Dispose();

            Assert.Single(serviceProviderEngineScope.ResolvedServices);
        }
        public void DoubleDisposeWorks()
        {
            var provider = new ServiceProvider(new ServiceCollection(), ServiceProviderOptions.Default);
            var serviceProviderEngineScope = new ServiceProviderEngineScope(provider, isRootScope: true);

            serviceProviderEngineScope.ResolvedServices.Add(new ServiceCacheKey(typeof(IFakeService), 0), null);
            serviceProviderEngineScope.Dispose();
            serviceProviderEngineScope.Dispose();
        }
 protected ServiceProviderEngine(IEnumerable <ServiceDescriptor> serviceDescriptors)
 {
     _createServiceAccessor = CreateServiceAccessor;
     Root            = new ServiceProviderEngineScope(this, isRoot: true);
     RuntimeResolver = new CallSiteRuntimeResolver();
     CallSiteFactory = new CallSiteFactory(serviceDescriptors);
     CallSiteFactory.Add(typeof(IServiceProvider), new ServiceProviderCallSite());
     CallSiteFactory.Add(typeof(IServiceScopeFactory), new ServiceScopeFactoryCallSite());
     RealizedServices = new ConcurrentDictionary <Type, Func <ServiceProviderEngineScope, object> >();
 }
Beispiel #9
0
 public ILEmitResolverBuilder(CallSiteRuntimeResolver runtimeResolver, IServiceScopeFactory serviceScopeFactory, ServiceProviderEngineScope rootScope)
 {
     if (runtimeResolver == null)
     {
         throw new ArgumentNullException(nameof(runtimeResolver));
     }
     _runtimeResolver     = runtimeResolver;
     _serviceScopeFactory = serviceScopeFactory;
     _rootScope           = rootScope;
 }
Beispiel #10
0
        public void ResolvedServicesAfterDispose_ThrowsObjectDispose()
        {
            var engine = new FakeEngine();
            var serviceProviderEngineScope = new ServiceProviderEngineScope(engine);

            serviceProviderEngineScope.ResolvedServices.Add(new ServiceCacheKey(typeof(IFakeService), 0), null);
            serviceProviderEngineScope.Dispose();

            Assert.Throws <ObjectDisposedException>(() => serviceProviderEngineScope.ResolvedServices);
        }
 protected ServiceProviderEngine(IEnumerable <ServiceDescriptor> serviceDescriptors, IServiceProviderEngineCallback callback)
 {
     _createServiceAccessor = CreateServiceAccessor;
     _callback       = callback;
     Root            = new ServiceProviderEngineScope(this); //实例化根容器
     RuntimeResolver = new CallSiteRuntimeResolver();        //实例化 CallSite对象访问者对象
     CallSiteFactory = new CallSiteFactory(serviceDescriptors);
     CallSiteFactory.Add(typeof(IServiceProvider), new ServiceProviderCallSite());
     CallSiteFactory.Add(typeof(IServiceScopeFactory), new ServiceScopeFactoryCallSite());             // 缓存一个ServiceScopeFactoryCallSite服务,相当于缓存一个ServiceProviderEngine,根据此对象进行创建子容器
     RealizedServices = new ConcurrentDictionary <Type, Func <ServiceProviderEngineScope, object> >(); //缓存实例化对象的工厂
 }
        /// <summary>
        /// 这个方法获取服务实例对象,可以看到具有两个此方法,并且第一个调用了第二个,并将顶级容器Root进行了传入,而在第二个方法中,获取并添加_createServiceAccessor委托,然后调用此委托进行获取服务实例
        /// </summary>
        /// <param name="serviceType"></param>
        /// <param name="serviceProviderEngineScope"></param>
        /// <returns></returns>
        internal object GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
        {
            if (_disposed)
            {
                ThrowHelper.ThrowObjectDisposedException();
            }

            var realizedService = RealizedServices.GetOrAdd(serviceType, _createServiceAccessor); //添加并获取根据容器对象实例化对象的方法,其方法由子类进行重写

            _callback?.OnResolve(serviceType, serviceProviderEngineScope);                        // 验证是否允许进行实例化对象
            return(realizedService.Invoke(serviceProviderEngineScope));
        }
Beispiel #13
0
        protected ServiceProviderEngine(IEnumerable <ServiceDescriptor> serviceDescriptors, IServiceProviderEngineCallback callback)
        {
            _createServiceAccessor = CreateServiceAccessor;
            _callback = callback;

            Root              = new ServiceProviderEngineScope(this);
            RuntimeResolver   = new CallSiteRuntimeResolver();
            ExpressionBuilder = new CallSiteExpressionBuilder(RuntimeResolver, this, Root);
            CallSiteFactory   = new CallSiteFactory(serviceDescriptors);
            CallSiteFactory.Add(typeof(IServiceProvider), new ServiceProviderCallSite());
            CallSiteFactory.Add(typeof(IServiceScopeFactory), new ServiceScopeFactoryCallSite());
        }
Beispiel #14
0
        internal object GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
        {
            if (_disposed)
            {
                ThrowHelper.ThrowObjectDisposedException();
            }

            var realizedService = RealizedServices.GetOrAdd(serviceType, _createServiceAccessor);

            _callback?.OnResolve(serviceType, serviceProviderEngineScope);
            return(realizedService.Invoke(serviceProviderEngineScope));
        }
Beispiel #15
0
        internal object GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope)
        {
            if (_disposed)
            {
                ThrowHelper.ThrowObjectDisposedException();
            }

            Func <ServiceProviderEngineScope, object> realizedService = RealizedServices.GetOrAdd(serviceType, _createServiceAccessor);

            _callback?.OnResolve(serviceType, serviceProviderEngineScope);
            DependencyInjectionEventSource.Log.ServiceResolved(serviceType);
            return(realizedService.Invoke(serviceProviderEngineScope));
        }
        public ExpressionResolverBuilder(CallSiteRuntimeResolver runtimeResolver, IServiceScopeFactory serviceScopeFactory, ServiceProviderEngineScope rootScope)
        {
            if (runtimeResolver == null)
            {
                throw new ArgumentNullException(nameof(runtimeResolver));
            }

            _scopeResolverCache  = new ConcurrentDictionary <ServiceCacheKey, Func <ServiceProviderEngineScope, object> >();
            _runtimeResolver     = runtimeResolver;
            _serviceScopeFactory = serviceScopeFactory;
            _rootScope           = rootScope;
            _buildTypeDelegate   = (key, cs) => BuildNoCache(cs);
        }
Beispiel #17
0
 public ILEmitResolverBuilder(CallSiteRuntimeResolver runtimeResolver, IServiceScopeFactory serviceScopeFactory, ServiceProviderEngineScope rootScope) :
     base()
 {
     if (runtimeResolver == null)
     {
         throw new ArgumentNullException(nameof(runtimeResolver));
     }
     _runtimeResolver     = runtimeResolver;
     _serviceScopeFactory = serviceScopeFactory;
     _rootScope           = rootScope;
     _scopeResolverCache  = new ConcurrentDictionary <ServiceCacheKey, GeneratedMethod>();
     _buildTypeDelegate   = (key, cs) => BuildTypeNoCache(cs);
 }
Beispiel #18
0
        internal object GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope) //获取服务类型对应的服务实例,首先会从 RealizedServices 中获取服务类型对应的创建实例方法 (如果没有就会在运行是将该方法加入 RealizedServices,运行时动态添加)。
                                                                                                            //获取的创建实例的委托方法需要一个类型为 ServiceProviderEngineScope 的参数才能调用,返回服务实例。
                                                                                                            //最后调用这个创建服务类型实例的方法。
        {
            if (_disposed)
            {
                ThrowHelper.ThrowObjectDisposedException();
            }

            var realizedService = RealizedServices.GetOrAdd(serviceType, _createServiceAccessor);

            _callback?.OnResolve(serviceType, serviceProviderEngineScope);
            return(realizedService.Invoke(serviceProviderEngineScope));
        }
Beispiel #19
0
 protected ServiceProviderEngine(
     IEnumerable <ServiceDescriptor> serviceDescriptors,
     IServiceProviderEngineCallback callback,
     IInterceptingProxyFactory interceptingProxyFactory)
 {
     _createServiceAccessor = CreateServiceAccessor;
     _callback       = callback;
     Root            = new ServiceProviderEngineScope(this);
     RuntimeResolver = new CallSiteRuntimeResolver();
     CallSiteFactory = new CallSiteFactory(serviceDescriptors, interceptingProxyFactory);
     CallSiteFactory.Add(typeof(IServiceProvider), new ServiceProviderCallSite());
     CallSiteFactory.Add(typeof(IServiceScopeFactory), new ServiceScopeFactoryCallSite());
     RealizedServices = new ConcurrentDictionary <Type, Func <ServiceProviderEngineScope, object> >();
 }
        private object VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
        {
            bool lockTaken = false;
            Dictionary <ServiceCacheKey, object> resolvedServices = serviceProviderEngine.ResolvedServices;

            // Taking locks only once allows us to fork resolution process
            // on another thread without causing the deadlock because we
            // always know that we are going to wait the other thread to finish before
            // releasing the lock
            if ((context.AcquiredLocks & lockType) == 0)
            {
                Monitor.Enter(resolvedServices, ref lockTaken);
            }

            try
            {
                return(ResolveService(callSite, context, lockType, serviceProviderEngine));
            }
            finally
            {
                if (lockTaken)
                {
                    Monitor.Exit(resolvedServices);
                }
            }
        }
        private object VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
        {
            bool   lockTaken = false;
            object sync      = serviceProviderEngine.Sync;
            Dictionary <ServiceCacheKey, object> resolvedServices = serviceProviderEngine.ResolvedServices;

            // Taking locks only once allows us to fork resolution process
            // on another thread without causing the deadlock because we
            // always know that we are going to wait the other thread to finish before
            // releasing the lock
            if ((context.AcquiredLocks & lockType) == 0)
            {
                Monitor.Enter(sync, ref lockTaken);
            }

            try
            {
                // Note: This method has already taken lock by the caller for resolution and access synchronization.
                // For scoped: takes a dictionary as both a resolution lock and a dictionary access lock.
                if (resolvedServices.TryGetValue(callSite.Cache.Key, out object resolved))
                {
                    return(resolved);
                }

                resolved = VisitCallSiteMain(callSite, new RuntimeResolverContext
                {
                    Scope         = serviceProviderEngine,
                    AcquiredLocks = context.AcquiredLocks | lockType
                });
                serviceProviderEngine.CaptureDisposable(resolved);
                resolvedServices.Add(callSite.Cache.Key, resolved);
                return(resolved);
            }
            finally
            {
                if (lockTaken)
                {
                    Monitor.Exit(sync);
                }
            }
        }
        private object ResolveService(ServiceCallSite callSite, RuntimeResolverContext context, RuntimeResolverLock lockType, ServiceProviderEngineScope serviceProviderEngine)
        {
            Dictionary <ServiceCacheKey, object> resolvedServices = serviceProviderEngine.ResolvedServices;

            if (!resolvedServices.TryGetValue(callSite.Cache.Key, out object resolved))
            {
                resolved = VisitCallSiteMain(callSite, new RuntimeResolverContext
                {
                    Scope         = serviceProviderEngine,
                    AcquiredLocks = context.AcquiredLocks | lockType
                });

                serviceProviderEngine.CaptureDisposable(resolved);
                resolvedServices.Add(callSite.Cache.Key, resolved);
            }

            return(resolved);
        }
        private object VisitCache(ServiceCallSite scopedCallSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType)
        {
            bool lockTaken        = false;
            var  resolvedServices = serviceProviderEngine.ResolvedServices;

            // Taking locks only once allows us to fork resolution process
            // on another thread without causing the deadlock because we
            // always know that we are going to wait the other thread to finish before
            // releasing the lock
            if ((context.AcquiredLocks & lockType) == 0)
            {
                Monitor.Enter(resolvedServices, ref lockTaken);
            }

            try
            {
                if (!resolvedServices.TryGetValue(scopedCallSite.Cache.Key, out var resolved))
                {
                    resolved = VisitCallSiteMain(scopedCallSite, new RuntimeResolverContext
                    {
                        Scope         = serviceProviderEngine,
                        AcquiredLocks = context.AcquiredLocks | lockType
                    });

                    serviceProviderEngine.CaptureDisposable(resolved);
                    resolvedServices.Add(scopedCallSite.Cache.Key, resolved);
                }

                return(resolved);
            }
            finally
            {
                if (lockTaken)
                {
                    Monitor.Exit(resolvedServices);
                }
            }
        }
Beispiel #24
0
 public ILEmitResolverBuilder(ServiceProvider serviceProvider)
 {
     _rootScope          = serviceProvider.Root;
     _scopeResolverCache = new ConcurrentDictionary <ServiceCacheKey, GeneratedMethod>();
     _buildTypeDelegate  = (key, cs) => BuildTypeNoCache(cs);
 }
Beispiel #25
0
 public ExpressionResolverBuilder(ServiceProvider serviceProvider)
 {
     _rootScope          = serviceProvider.Root;
     _scopeResolverCache = new ConcurrentDictionary <ServiceCacheKey, Func <ServiceProviderEngineScope, object> >();
     _buildTypeDelegate  = (key, cs) => BuildNoCache(cs);
 }
        private object ResolveService(ServiceCallSite callSite, RuntimeResolverContext context, RuntimeResolverLock lockType, ServiceProviderEngineScope serviceProviderEngine)
        {
            IDictionary <ServiceCacheKey, object> resolvedServices = serviceProviderEngine.ResolvedServices;

            // Note: This method has already taken lock by the caller for resolution and access synchronization.
            // For root: uses a concurrent dictionary and takes a per singleton lock for resolution.
            // For scoped: takes a dictionary as both a resolution lock and a dictionary access lock.
            Debug.Assert(
                (lockType == RuntimeResolverLock.Root && resolvedServices is ConcurrentDictionary <ServiceCacheKey, object>) ||
                (lockType == RuntimeResolverLock.Scope && Monitor.IsEntered(resolvedServices)));

            if (resolvedServices.TryGetValue(callSite.Cache.Key, out object resolved))
            {
                return(resolved);
            }

            resolved = VisitCallSiteMain(callSite, new RuntimeResolverContext
            {
                Scope         = serviceProviderEngine,
                AcquiredLocks = context.AcquiredLocks | lockType
            });
            serviceProviderEngine.CaptureDisposable(resolved);
            resolvedServices.Add(callSite.Cache.Key, resolved);
            return(resolved);
        }