Пример #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="IxHost"/> class.
        /// This is first build phase. Second phase performed by <see cref="Initialize"/>.
        /// </summary>
        public IxHost()
        {
            _argumentProvider = new IxArgumentProvider(this);

            // TODO: Load priorities from configs.
            InstanceFactoryBuilder.Add(ExistingInstanceRawFactoryBuilder, 100);
            InstanceFactoryBuilder.Add(ClassInstanceFactoryBuilder, 200);
            InstanceFactoryBuilder.Add(DelegateInstanceBuilder, 300);

            VisibilityFilterBuilder.Add(StdVisibilityFilterBuilder, 100);

            ProviderNodeBuilder.Add(StdProviderConfigDefaultsSetter, 100);
            ProviderNodeBuilder.Add(ScopeBuilder, 200);
            ProviderNodeBuilder.Add(SingletonProviderBuilder, 300);
            ProviderNodeBuilder.Add(PerResolveProviderBuilder, 400);

            ScopeBinderBuilder.Add(RegistrationScopeBinderBuilder, 100);

            DisposeHandlerBuilder.Add(DisposableDisposeHandlerBuilder, 100);
            DisposeHandlerBuilder.Add(AsyncDisposableDisposeHandlerBuilder, 200);

            ResolveHandler.Add(SelfResolveInterceptor, 80);
            ResolveHandler.Add(ResolverResolveInterceptor, 100);
            ResolveHandler.Add(DirectCycleResolveInterceptor, 150);
            ResolveHandler.Add(SelfToChildrenResolver, 200);
            ResolveHandler.Add(StdResolveInterceptor, 300);
            ResolveHandler.Add(ResolveContextResolveInterceptor, 400);
        }
Пример #2
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;
            }
        }