/// <summary>
        /// Releases item from pool's locked item list
        /// </summary>
        public void ReleasePoolItem <TService>(TService service)
        {
            BuiltServiceDescriptor descriptor = _services[typeof(TService)];
            IServicePool           pool       = (IServicePool)descriptor.Instance;

            pool.ReleaseInstance(service);
        }
        internal object GetWithDescriptor(BuiltServiceDescriptor descriptor, IContainerScope scope)
        {
            if (descriptor.IsPool)
            {
                return(GetFromPool(descriptor, scope));
            }

            if (descriptor.Implementation == ImplementationType.Scoped && scope == null)
            {
                throw new ScopeException($"{descriptor.ServiceType.ToTypeString()} is registered as scoped service but trying to create instance when scope is null");
            }

            object service;

            if (scope != null && descriptor.Implementation == ImplementationType.Scoped)
            {
                service = scope.Get(descriptor.ServiceType);
            }
            else
            {
                service = descriptor.CreateInstance(this, scope);
            }

            return(ApplyAfterGet(descriptor, service));
        }
        internal object Get(Type serviceType, bool executedFromScope, IContainerScope scope = null)
        {
            //throw new NullReferenceException($"Could not get service from container: {typeof(TService).ToTypeString()}");
            //throw new KeyNotFoundException($"Service type is not found: {serviceType.ToTypeString()}");

            BuiltServiceDescriptor descriptor = _services[serviceType];

            if (descriptor.IsPool)
            {
                return(GetFromPool(descriptor, scope));
            }

            if (descriptor.Implementation == ImplementationType.Scoped && scope == null)
            {
                throw new ScopeException($"{serviceType.ToTypeString()} is registered as scoped service but trying to create instance when scope is null");
            }

            if (descriptor.Instance != null)
            {
                return(ApplyAfterGet(descriptor, descriptor.Instance));
            }

            object service;

            if (!executedFromScope && scope != null && descriptor.Implementation == ImplementationType.Scoped)
            {
                service = scope.Get(serviceType);
            }
            else
            {
                service = descriptor.CreateInstance(this, scope);
            }

            return(ApplyAfterGet(descriptor, service));
        }
        private void FillParameterDescriptors(BuiltServiceDescriptor descriptor, BuiltServiceDescriptor root)
        {
            if (descriptor.Parameters == null)
            {
                return;
            }

            if (root.Parameters != null && descriptor.Parameters != null)
            {
                if (descriptor.Parameters.Contains(root.ServiceType))
                {
                    throw new CircularReferenceException($"Circular reference between {root.ServiceType.ToTypeString()} and {descriptor.ServiceType.ToTypeString()}");
                }
            }

            foreach (Type type in descriptor.Parameters)
            {
                if (!_services.ContainsKey(type))
                {
                    throw new MissingReferenceException($"{descriptor.ServiceType.ToTypeString()} requires {type.ToTypeString()} but it's not registered");
                }

                BuiltServiceDescriptor parameterDescriptor = _services[type];
                descriptor.ParameterDescriptors.Add(parameterDescriptor);
                FillParameterDescriptors(parameterDescriptor, root);
            }
        }
예제 #5
0
        public object CreateInstance(TwinoServiceProvider provider, IContainerScope scope = null)
        {
            if (!IsPool && Instance != null)
            {
                return(Instance);
            }

            object service;

            if (ImplementationFactory != null)
            {
                service = ImplementationFactory(provider);
                ExecuteAfterCreated(service);
                return(service);
            }

            if (Parameters == null || Parameters.Length == 0)
            {
                service = _instanceCreatorFunctionParameterless();
                ExecuteAfterCreated(service);
                return(service);
            }

            if (Parameters.Length == 1)
            {
                BuiltServiceDescriptor descriptor = ParameterDescriptors[0];
                object parameter = provider.GetWithDescriptor(descriptor, scope);
                service = _instanceCreatorFunctionOneParameter(parameter);
                ExecuteAfterCreated(service);
                return(service);
            }

            object[] p = new object[ParameterDescriptors.Count];
            for (int i = 0; i < p.Length; i++)
            {
                BuiltServiceDescriptor descriptor = ParameterDescriptors[i];
                p[i] = provider.GetWithDescriptor(descriptor, scope);
            }

            service = _instanceCreatorFunctionMultipleParameters(p);
            ExecuteAfterCreated(service);
            return(service);
        }
        private object ApplyAfterGet(BuiltServiceDescriptor descriptor, object service)
        {
            if (descriptor.ProxyInstance != null)
            {
                service = descriptor.ProxyInstance.Proxy(service);
            }

            else if (descriptor.ProxyType != null)
            {
                IServiceProxy proxy = (IServiceProxy)Get(descriptor.ProxyType);
                service = proxy.Proxy(service);
            }

            if (descriptor.Implementation == ImplementationType.Singleton)
            {
                descriptor.Instance = service;
            }

            return(service);
        }
        private object GetFromPool(BuiltServiceDescriptor descriptor, IContainerScope scope)
        {
            IServicePool          pool  = (IServicePool)descriptor.Instance;
            PoolServiceDescriptor pdesc = pool.GetAndLock(scope);

            if (pdesc == null)
            {
                throw new NullReferenceException($"{descriptor.ServiceType.ToTypeString()} Service is not registered in the container");
            }

            if (pool.Type == ImplementationType.Scoped && scope == null)
            {
                throw new ScopeException($"{descriptor.ServiceType.ToTypeString()} is registered as Scoped but scope parameter is null for IServiceContainer.Get method");
            }

            if (scope != null)
            {
                scope.UsePoolItem(pool, pdesc);
            }

            return(pdesc.GetInstance());
        }
        private BuiltServiceDescriptor BuildItem(TwinoServiceDescriptor descriptor, IEnumerable <TwinoServiceDescriptor> services)
        {
            ConstructorHelper      ctorHelper      = new ConstructorHelper(services);
            BuiltServiceDescriptor builtDescriptor = new BuiltServiceDescriptor(descriptor.Implementation,
                                                                                descriptor.ServiceType,
                                                                                descriptor.ImplementationType);


            builtDescriptor.Instance = descriptor.Instance;
            builtDescriptor.ImplementationFactory = descriptor.ImplementationFactory;
            builtDescriptor.IsPool             = descriptor.IsPool;
            builtDescriptor.AfterCreatedMethod = descriptor.AfterCreatedMethod;

            //we need to find a ctor to create instance
            if (builtDescriptor.IsPool || builtDescriptor.Instance == null && builtDescriptor.ImplementationFactory == null)
            {
                ConstructorInfo constructorInfo = ctorHelper.FindAvailableConstructor(descriptor.ImplementationType);
                if (constructorInfo == null)
                {
                    throw new IocConstructorException($"{descriptor.ServiceType.ToTypeString()} does not have available constructor");
                }

                builtDescriptor.Build(constructorInfo);
            }

            _services.Add(descriptor.ServiceType, builtDescriptor);
            if (builtDescriptor.IsPool)
            {
                if (builtDescriptor.Instance is IServicePoolInternal pool)
                {
                    pool.SetBuiltDescriptor(builtDescriptor);
                }
            }

            return(builtDescriptor);
        }