private void InstantiateImplementation(ContainerService.Builder builder)
        {
            if (builder.DontUse())
            {
                builder.SetComment("DontUse");
                return;
            }
            var result = FactoryCreator.TryCreate(builder) ?? LazyCreator.TryCreate(builder);

            if (result != null)
            {
                builder.AddInstance(result, true, false);
                return;
            }
            if (NestedFactoryCreator.TryCreate(builder))
            {
                return;
            }
            if (CtorFactoryCreator.TryCreate(builder))
            {
                return;
            }
            if (builder.Type.IsDelegate())
            {
                builder.SetError(string.Format("can't create delegate [{0}]", builder.Type.FormatName()));
                return;
            }
            var constructor = builder.Type.GetConstructor();

            if (!constructor.isOk)
            {
                builder.SetError(constructor.errorMessage);
                return;
            }
            var formalParameters         = constructor.value.GetParameters();
            var actualArguments          = new object[formalParameters.Length];
            var hasServiceNameParameters = false;

            for (var i = 0; i < formalParameters.Length; i++)
            {
                var formalParameter = formalParameters[i];
                if (formalParameter.ParameterType == typeof(ServiceName))
                {
                    hasServiceNameParameters = true;
                    continue;
                }
                var dependency = InstantiateDependency(formalParameter, builder).CastTo(formalParameter.ParameterType);
                builder.AddDependency(dependency, false);
                if (dependency.ContainerService != null)
                {
                    builder.UnionUsedContracts(dependency.ContainerService);
                }
                if (builder.Status != ServiceStatus.Ok && !builder.Context.AnalizeDependenciesOnly)
                {
                    return;
                }
                actualArguments[i] = dependency.Value;
            }
            foreach (var d in builder.Configuration.ImplicitDependencies)
            {
                var dependency = ResolveCore(ServiceName.Parse(d.Type, d.Contracts), false, null, builder.Context)
                                 .AsDependency(containerContext, null, false);
                dependency.Comment = "implicit";
                builder.AddDependency(dependency, false);
                if (dependency.ContainerService != null)
                {
                    builder.UnionUsedContracts(dependency.ContainerService);
                }
                if (builder.Status != ServiceStatus.Ok)
                {
                    return;
                }
            }
            builder.EndResolveDependencies();
            if (builder.Context.AnalizeDependenciesOnly)
            {
                return;
            }
            var           dependenciesResolvedByArguments = builder.Arguments == null ? null : builder.Arguments.GetUsed();
            List <string> unusedConfigurationKeys         = null;

            foreach (var k in builder.Configuration.GetUnusedDependencyKeys())
            {
                var resolvedByArguments = dependenciesResolvedByArguments != null &&
                                          k.name != null &&
                                          dependenciesResolvedByArguments.Contains(k.name);
                if (resolvedByArguments)
                {
                    continue;
                }
                if (unusedConfigurationKeys == null)
                {
                    unusedConfigurationKeys = new List <string>();
                }
                unusedConfigurationKeys.Add(k.ToString());
            }
            if (unusedConfigurationKeys != null)
            {
                builder.SetError(string.Format("unused dependency configurations [{0}]", unusedConfigurationKeys.JoinStrings(",")));
                return;
            }
            if (hasServiceNameParameters)
            {
                for (var i = 0; i < formalParameters.Length; i++)
                {
                    if (formalParameters[i].ParameterType == typeof(ServiceName))
                    {
                        actualArguments[i] = builder.GetFinalName();
                    }
                }
            }
            if (builder.CreateNew || builder.DeclaredContracts.Length == builder.FinalUsedContracts.Length)
            {
                builder.CreateInstanceBy(CallTarget.M(constructor.value, null, actualArguments), true);
                if (builder.CreateNew && builder.Arguments == null)
                {
                    var compiledConstructor = constructor.value.Compile();
                    factoryCache.TryAdd(builder.GetFinalName(), () =>
                    {
                        var instance  = compiledConstructor(null, actualArguments);
                        var component = instance as IInitializable;
                        if (component != null)
                        {
                            component.Initialize();
                        }
                        return(instance);
                    });
                }
                return;
            }
            var serviceForUsedContractsId = instanceCache.GetOrAdd(builder.GetFinalName(), createId);
            var acquireResult             = serviceForUsedContractsId.AcquireInstantiateLock();

            if (acquireResult.acquired)
            {
                builder.CreateInstanceBy(CallTarget.M(constructor.value, null, actualArguments), true);
                serviceForUsedContractsId.ReleaseInstantiateLock(builder.Context.AnalizeDependenciesOnly
                                        ? null
                                        : builder.GetService());
            }
            else
            {
                builder.Reuse(acquireResult.alreadyConstructedService);
            }
        }
        private void InstantiateInterface(ContainerService.Builder builder)
        {
            HashSet <ImplementationType> implementationTypes;

            try
            {
                implementationTypes = GetImplementationTypes(builder);
            }
            catch (Exception e)
            {
                builder.SetError(e);
                return;
            }
            ApplySelectors(implementationTypes, builder);
            if (implementationTypes.Count == 0)
            {
                builder.SetComment("has no implementations");
                return;
            }
            Func <object> factory       = null;
            var           canUseFactory = true;

            foreach (var implementationType in implementationTypes)
            {
                if (implementationType.accepted)
                {
                    var implementationService = ResolveCore(ServiceName.Parse(implementationType.type, InternalHelpers.emptyStrings),
                                                            builder.CreateNew, builder.Arguments, builder.Context);
                    builder.LinkTo(containerContext, implementationService, implementationType.comment);
                    if (builder.CreateNew && builder.Arguments == null &&
                        implementationService.Status == ServiceStatus.Ok && canUseFactory)
                    {
                        if (factory == null)
                        {
                            if (!factoryCache.TryGetValue(implementationService.Name, out factory))
                            {
                                canUseFactory = false;
                            }
                        }
                        else
                        {
                            canUseFactory = false;
                        }
                    }
                    if (builder.Status.IsBad())
                    {
                        return;
                    }
                }
                else
                {
                    var dependency = containerContext.NotResolved(null, implementationType.type.FormatName());
                    dependency.Comment = implementationType.comment;
                    builder.AddDependency(dependency, true);
                }
            }
            builder.EndResolveDependencies();
            if (factory != null && canUseFactory)
            {
                factoryCache.TryAdd(builder.GetFinalName(), factory);
            }
        }