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);
            }
        }
        internal ContainerService ResolveCore(ServiceName name, bool createNew, IObjectAccessor arguments, ResolutionContext context)
        {
            var pushedContracts = context.Contracts.Push(name.Contracts);
            var declaredName = new ServiceName(name.Type, context.Contracts.Snapshot());
            if (context.HasCycle(declaredName))
            {
                var message = string.Format("cyclic dependency for service [{0}], stack\r\n{1}",
                    declaredName.Type.FormatName(), context.FormatStack() + "\r\n\t" + declaredName);
                context.Contracts.RemoveLast(pushedContracts.pushedContractsCount);
                return ContainerService.Error(declaredName, message);
            }
            if (!pushedContracts.isOk)
            {
                const string messageFormat = "contract [{0}] already declared, stack\r\n{1}";
                var message = string.Format(messageFormat, pushedContracts.duplicatedContractName,
                    context.FormatStack() + "\r\n\t" + name);
                context.Contracts.RemoveLast(pushedContracts.pushedContractsCount);
                return ContainerService.Error(name, message);
            }
            context.ConstructingServices.Add(declaredName);

            ServiceConfiguration configuration = null;
            Exception configurationException = null;
            try
            {
                configuration = GetConfiguration(declaredName.Type, context);
            }
            catch (Exception e)
            {
                configurationException = e;
            }
            var actualName = configuration != null && configuration.FactoryDependsOnTarget && context.Stack.Count > 0
                ? declaredName.AddContracts(context.TopBuilder.Type.FormatName())
                : declaredName;
            ContainerServiceId id = null;
            if (!createNew)
            {
                id = instanceCache.GetOrAdd(actualName, createId);
                var acquireResult = id.AcquireInstantiateLock();
                if (!acquireResult.acquired)
                {
                    context.ConstructingServices.Remove(declaredName);
                    context.Contracts.RemoveLast(pushedContracts.pushedContractsCount);
                    return acquireResult.alreadyConstructedService;
                }
            }
            var builder = new ContainerService.Builder(actualName);
            context.Stack.Add(builder);
            builder.Context = context;
            builder.DeclaredContracts = actualName.Contracts;
            if (configuration == null)
                builder.SetError(configurationException);
            else
            {
                builder.SetConfiguration(configuration);
                builder.ExpandedUnions = context.Contracts.TryExpandUnions(Configuration);
                if (builder.ExpandedUnions.HasValue)
                {
                    var poppedContracts = context.Contracts.PopMany(builder.ExpandedUnions.Value.contracts.Length);
                    foreach (var c in builder.ExpandedUnions.Value.contracts.CartesianProduct())
                    {
                        var childService = ResolveCore(new ServiceName(name.Type, c), createNew, arguments, context);
                        builder.LinkTo(containerContext, childService, null);
                        if (builder.Status.IsBad())
                            break;
                    }
                    context.Contracts.PushNoCheck(poppedContracts);
                }
                else
                {
                    builder.CreateNew = createNew;
                    builder.Arguments = arguments;
                    Instantiate(builder);
                }
            }
            context.ConstructingServices.Remove(declaredName);
            context.Contracts.RemoveLast(pushedContracts.pushedContractsCount);
            context.Stack.RemoveLast();
            var result = builder.GetService();
            if (id != null)
                id.ReleaseInstantiateLock(builder.Context.AnalizeDependenciesOnly ? null : result);
            return result;
        }
        internal ContainerService ResolveCore(ServiceName name, bool createNew, IObjectAccessor arguments, ResolutionContext context)
        {
            var pushedContracts = context.Contracts.Push(name.Contracts);
            var declaredName    = new ServiceName(name.Type, context.Contracts.Snapshot());

            if (context.HasCycle(declaredName))
            {
                var message = string.Format("cyclic dependency for service [{0}], stack\r\n{1}",
                                            declaredName.Type.FormatName(), context.FormatStack() + "\r\n\t" + declaredName);
                context.Contracts.RemoveLast(pushedContracts.pushedContractsCount);
                return(ContainerService.Error(declaredName, message));
            }
            if (!pushedContracts.isOk)
            {
                const string messageFormat = "contract [{0}] already declared, stack\r\n{1}";
                var          message       = string.Format(messageFormat, pushedContracts.duplicatedContractName,
                                                           context.FormatStack() + "\r\n\t" + name);
                context.Contracts.RemoveLast(pushedContracts.pushedContractsCount);
                return(ContainerService.Error(name, message));
            }
            context.ConstructingServices.Add(declaredName);

            ServiceConfiguration configuration          = null;
            Exception            configurationException = null;

            try
            {
                configuration = GetConfiguration(declaredName.Type, context);
            }
            catch (Exception e)
            {
                configurationException = e;
            }
            var actualName = configuration != null && configuration.FactoryDependsOnTarget && context.Stack.Count > 0
                                ? declaredName.AddContracts(context.TopBuilder.Type.FormatName())
                                : declaredName;
            ContainerServiceId id = null;

            if (!createNew)
            {
                id = instanceCache.GetOrAdd(actualName, createId);
                var acquireResult = id.AcquireInstantiateLock();
                if (!acquireResult.acquired)
                {
                    context.ConstructingServices.Remove(declaredName);
                    context.Contracts.RemoveLast(pushedContracts.pushedContractsCount);
                    return(acquireResult.alreadyConstructedService);
                }
            }
            var builder = new ContainerService.Builder(actualName);

            context.Stack.Add(builder);
            builder.Context           = context;
            builder.DeclaredContracts = actualName.Contracts;
            if (configuration == null)
            {
                builder.SetError(configurationException);
            }
            else
            {
                builder.SetConfiguration(configuration);
                builder.ExpandedUnions = context.Contracts.TryExpandUnions(Configuration);
                if (builder.ExpandedUnions.HasValue)
                {
                    var poppedContracts = context.Contracts.PopMany(builder.ExpandedUnions.Value.contracts.Length);
                    foreach (var c in builder.ExpandedUnions.Value.contracts.CartesianProduct())
                    {
                        var childService = ResolveCore(new ServiceName(name.Type, c), createNew, arguments, context);
                        builder.LinkTo(containerContext, childService, null);
                        if (builder.Status.IsBad())
                        {
                            break;
                        }
                    }
                    context.Contracts.PushNoCheck(poppedContracts);
                }
                else
                {
                    builder.CreateNew = createNew;
                    builder.Arguments = arguments;
                    Instantiate(builder);
                }
            }
            context.ConstructingServices.Remove(declaredName);
            context.Contracts.RemoveLast(pushedContracts.pushedContractsCount);
            context.Stack.RemoveLast();
            var result = builder.GetService();

            if (id != null)
            {
                id.ReleaseInstantiateLock(builder.Context.AnalizeDependenciesOnly ? null : result);
            }
            return(result);
        }
 public ContainerService Instantiate(Type type, bool crearteNew, IObjectAccessor arguments)
 {
     var builder = new ContainerService.Builder(type, this, crearteNew, arguments);
     if (builder.Status != ServiceStatus.Ok)
         return builder.Build();
     var declaredName = builder.GetDeclaredName();
     if (!constructingServices.Add(declaredName))
     {
         var previous = GetTopBuilder();
         if (previous == null)
             throw new InvalidOperationException(string.Format("assertion failure, service [{0}]", declaredName));
         var message = string.Format("cyclic dependency {0}{1} -> {0}",
             type.FormatName(), previous.Type == type ? "" : " ...-> " + previous.Type.FormatName());
         var cycleBuilder = new ContainerService.Builder(type, this, false, null);
         cycleBuilder.SetError(message);
         return cycleBuilder.Build();
     }
     stack.Add(builder);
     var expandResult = TryExpandUnions(Container.Configuration);
     if (expandResult != null)
     {
         var poppedContracts = Contracts.PopMany(expandResult.Length);
         foreach (var c in expandResult.CartesianProduct())
         {
             var childService = Resolve(new ServiceName(builder.Type, c));
             builder.LinkTo(Container.containerContext, childService, null);
             if (builder.Status.IsBad())
                 break;
         }
         Contracts.AddRange(poppedContracts);
     }
     else
         Container.Instantiate(builder);
     stack.RemoveLast();
     constructingServices.Remove(declaredName);
     return builder.Build();
 }