예제 #1
0
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously

        /// <inheritdoc/>
        public override async ValueTask <IIxInstanceLock> GetInstance(
            IIxInstance parentInstance,
            IxIdentifier identifier,
            IxHost.IxResolveContext context,
            [CanBeNull] IxResolveFrame frame)
        {
            if (parentInstance == null)
            {
                throw new ArgumentNullException(nameof(parentInstance));
            }

            lock (Host.InstanceTreeSyncRoot)
            {
                IIxInstanceLock scopeLock;
                IxScopeInstance singleton;
                object          data = parentInstance.GetData(this);
                if (data == null)
                {
                    singleton = new IxScopeInstance(this, parentInstance, out scopeLock);
                    parentInstance.SetData(this, singleton);
                }
                else
                {
                    singleton = (IxScopeInstance)data;
                    scopeLock = new IxInstancePinLock(singleton);
                }

                return(scopeLock);
            }
        }
예제 #2
0
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously

        public IxScopeInstance GetRootInstance()
        {
            if (ParentNode != null)
            {
                throw new InvalidOperationException("Only root scope can produce root instance.");
            }

            if (_rootInstance == null)
            {
                lock (Host.InstanceTreeSyncRoot)
                {
                    if (_rootInstance == null)
                    {
                        IIxInstanceLock creatorLock;
                        _rootInstance = new IxScopeInstance(this, null, out creatorLock);
                        creatorLock.Dispose();
                    }
                }
            }

            return(_rootInstance);
        }
예제 #3
0
        /// <summary>
        /// Second initialization phase.
        /// </summary>
        /// <param name="config">Host configuration.</param>
        /// <returns>Async execution TPL task.</returns>
        public async Task Initialize(IIxHostConfig config)
        {
            var allConfigNodes = new HashSet <IIxProviderNodeConfig>();

            config.Nodes.Add(
                new IxStdProviderConfig
            {
                Identifier      = new IxIdentifier(typeof(IIxHost)),
                InstanceBuilder = new IxExistingInstanceFactoryConfig <IIxHost>(this),
                DisposeHandler  = obj => TaskEx.CompletedTask
            });

            Action <IIxProviderNodeConfig, IxProviderNode> buildNodeAction = null;

            buildNodeAction = (nodeConfig, parentNode) =>
            {
                if (!allConfigNodes.Add(nodeConfig))
                {
                    throw new InvalidOperationException(
                              "Configuration contains the same object multiple times. Currently it's not allowed to avoid visitor cycles.");
                }

                IxProviderNode node = ProviderNodeBuilder.Delegate(nodeConfig, parentNode);

                // parent node is null only for root scope.
                if (parentNode == null)
                {
                    _rootScope = (IxScope)node;
                }

                foreach (IIxProviderNodeConfig childConfig in nodeConfig.Nodes)
                {
                    buildNodeAction(childConfig, node);
                }
            };

            buildNodeAction(config, null);

            Action <IxProviderNode> importRegistrationsFromChildren = null;

            importRegistrationsFromChildren = node =>
            {
                foreach (IxProviderNode child in node.Nodes)
                {
                    importRegistrationsFromChildren(child);

                    // Applying export to parent filter
                    // while Blocking from exporting resolve pathes with zero-length.
                    foreach (KeyValuePair <IxIdentifier, IxResolvePath> kvp in
                             child.VisibleNodes.Where(
                                 x => child.ExportToParentFilter(x.Key) &&
                                 x.Value.Path.Any()))
                    {
                        if (node.VisibleNodes.ContainsKey(kvp.Key))
                        {
                            throw new InvalidOperationException("Export to parent node conflict.");
                        }

                        node.VisibleNodes.Add(kvp.Key, kvp.Value.ReRoot(node));
                    }
                }
            };

            importRegistrationsFromChildren(_rootScope);

            Action <IxProviderNode> exportRegistrationsToChildren = null;

            exportRegistrationsToChildren = node =>
            {
                KeyValuePair <IxIdentifier, IxResolvePath>[] registrationsToExport =
                    node.VisibleNodes.Where(x => node.ExportFilter(x.Key)).ToArray();

                if (!registrationsToExport.Any())
                {
                    return;
                }

                foreach (IxProviderNode child in node.Nodes)
                {
                    foreach (KeyValuePair <IxIdentifier, IxResolvePath> kvp in
                             registrationsToExport.Where(x => child.ImportFilter(x.Key)))
                    {
                        IxResolvePath resolvePath;
                        if (child.VisibleNodes.TryGetValue(kvp.Key, out resolvePath))
                        {
                            // Skipping self to children.
                            if (resolvePath.Path.Any())
                            {
                                // Direct cycle resolution replacement.
                                if (!resolvePath.Target.ParentReplacementNodes.ContainsKey(kvp.Key))
                                {
                                    resolvePath.Target.ParentReplacementNodes.Add(kvp.Key, kvp.Value);
                                }
                            }
                        }
                        else
                        {
                            child.VisibleNodes.Add(kvp.Key, kvp.Value);
                        }
                    }

                    exportRegistrationsToChildren(child);
                }
            };

            exportRegistrationsToChildren(_rootScope);

            _rootScopeInstance = _rootScope.GetRootInstance();
            var resolveContext = new IxResolveContext(_rootScopeInstance, null, new Dictionary <IxIdentifier, object>());

            using (IIxInstanceLock rootResolverLock = await Resolve(
                       _rootScopeInstance,
                       new IxIdentifier(typeof(IIxResolver)),
                       resolveContext,
                       null))
            {
                var resolver = (IxResolver)rootResolverLock.Target.Object;
                Critical.CheckedAssert(
                    resolver.ParentContext == null && resolver.ParentFrame == null,
                    "After resolve finished, resolver should not be bound to any context.");

                Resolver = resolver;
            }
        }