Beispiel #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="IxSingletonInstance"/> class.
        /// </summary>
        /// <param name="providerNode">Singleton provider.</param>
        /// <param name="parentInstance">Parent instance.</param>
        /// <param name="context">The resolve context.</param>
        /// <param name="frame">The resolution frame in the resolve sequence.</param>
        /// <param name="creatorTempLock">First temp lock for the creator of a new instance.</param>
        public IxSingletonInstance(
            IxSingletonProvider providerNode,
            IIxInstance parentInstance,
            IxHost.IxResolveContext context,
            [CanBeNull] IxResolveFrame frame,
            out IIxInstanceLock creatorTempLock)
            : base(providerNode, parentInstance, out creatorTempLock)
        {
            if (parentInstance == null)
            {
                throw new ArgumentNullException(nameof(parentInstance));
            }

            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            Debug.Assert(ProviderNode.InstanceFactory != null, "IxSingletonProvider always have instance factory.");

            var newFrame = new IxResolveFrame(frame, this);

            SetObjectCreationTask(
                ProviderNode.InstanceFactory.Factory(
                    this,
                    parentInstance,
                    context,
                    newFrame));
        }
Beispiel #2
0
        private async ValueTask <IIxInstanceLock> Resolve(
            IIxInstance originInstance,
            IxIdentifier identifier,
            IxResolveContext context,
            [CanBeNull] IxResolveFrame frame)
        {
            if (originInstance == null)
            {
                throw new ArgumentNullException(nameof(originInstance));
            }

            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (originInstance.ProviderNode.Host != this)
            {
                throw new InvalidOperationException("You cannot use resolver from different host.");
            }

            ////if (context.IsFailed)
            ////{
            ////    throw new InvalidOperationException("You cannot do anything inside failed resolve context.");
            ////}
            return(await ResolveHandler.Delegate(originInstance, identifier, context, frame));
        }
Beispiel #3
0
            public IxResolver(
                IxHost host,
                IIxInstance ownerInstance,
                [CanBeNull] IxResolveContext parentContext,
                [CanBeNull] IxResolveFrame parentFrame)
            {
                if (host == null)
                {
                    throw new ArgumentNullException(nameof(host));
                }

                if (ownerInstance == null)
                {
                    throw new ArgumentNullException(nameof(ownerInstance));
                }

                if (parentFrame != null)
                {
                    if (parentContext == null)
                    {
                        throw new ArgumentNullException();
                    }
                }

                Host          = host;
                OwnerInstance = ownerInstance;
                ParentFrame   = parentFrame;
                ParentContext = parentContext;
            }
Beispiel #4
0
 public IxResolveFrame(
     [CanBeNull] IxResolveFrame parentFrame,
     IIxInstance instance)
 {
     ParentFrame = parentFrame;
     Instance    = instance;
 }
Beispiel #5
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);
            }
        }
Beispiel #6
0
        /// <summary>
        /// Resolves list of <c>dependencies</c> from the specified origin. TODO: Implement <c>this</c> method with parallel
        /// resolution.
        /// </summary>
        /// <typeparam name="TResult">Target operation result type.</typeparam>
        /// <param name="originInstance">Origin instance. Where <c>dependencies</c> are queried.</param>
        /// <param name="dependencies">List of dependency identifiers.</param>
        /// <param name="context">Resolve <c>context</c>.</param>
        /// <param name="frame">The resolve sequence frame.</param>
        /// <param name="targetOperation">Operation that should be performed with resolved <c>dependencies</c>.</param>
        /// <returns>Result of target opration.</returns>
        public async ValueTask <TResult> ResolveList <TResult>(
            IIxInstance originInstance,
            HashSet <IxIdentifier> dependencies,
            IxResolveContext context,
            [CanBeNull] IxResolveFrame frame,
            Func <Dictionary <IxIdentifier, IIxInstance>, ValueTask <TResult> > targetOperation)
        {
            if (originInstance == null)
            {
                throw new ArgumentNullException(nameof(originInstance));
            }

            if (dependencies == null)
            {
                throw new ArgumentNullException(nameof(dependencies));
            }

            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (targetOperation == null)
            {
                throw new ArgumentNullException(nameof(targetOperation));
            }

            using (HashSet <IxIdentifier> .Enumerator enumerator = dependencies.GetEnumerator())
            {
                var result = new Dictionary <IxIdentifier, IIxInstance>();

                async ValueTask <TResult> ResolveItem()
                {
                    // ReSharper disable once AccessToDisposedClosure
                    if (!enumerator.MoveNext())
                    {
                        return(await targetOperation(result));
                    }

                    // ReSharper disable once AccessToDisposedClosure
                    IxIdentifier identifier = enumerator.Current;

                    using (IIxInstanceLock instanceLock = await Resolve(originInstance, identifier, context, frame))
                    {
                        result.Add(identifier, instanceLock.Target);
                        TResult resultItem = await ResolveItem();

                        if (identifier.Type == typeof(IIxResolver))
                        {
                            (instanceLock.Target as IxResolver)?.ClearParentResolveContext();
                        }

                        return(resultItem);
                    }
                }

                return(await ResolveItem());
            }
        }
Beispiel #7
0
 public override ValueTask <IIxInstanceLock> GetInstance(
     IIxInstance parentInstance,
     IxIdentifier identifier,
     IxHost.IxResolveContext context,
     [CanBeNull] IxResolveFrame frame)
 {
     throw new NotImplementedException();
 }
Beispiel #8
0
 /// <inheritdoc/>
 public override async ValueTask <IIxInstanceLock> GetInstance(
     IIxInstance parentInstance,
     IxIdentifier identifier,
     IxHost.IxResolveContext context,
     [CanBeNull] IxResolveFrame frame)
 {
     Critical.Assert(false, "Not supported.");
     return(null);
 }
Beispiel #9
0
        /// <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));
            }

            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            IIxInstanceLock     creatorLock = null;
            IxSingletonInstance instance;

            // Re-implement this with more advanced Half-Instantiation with loop detection.
            lock (Host.InstanceTreeSyncRoot)
            {
                instance = parentInstance.GetData(this) as IxSingletonInstance;
                if (instance == null)
                {
                    // TODO: Detect cycles.
                    Debug.Assert(InstanceFactory != null, "InstanceFactory != null");

                    instance = new IxSingletonInstance(this, parentInstance, context, frame, out creatorLock);

                    parentInstance.SetData(this, instance);
                }
            }

            try
            {
                await instance.ObjectCreationTask;
                return(creatorLock ?? new IxInstancePinLock(instance));
            }
            catch
            {
                if (creatorLock != null)
                {
                    lock (Host.InstanceTreeSyncRoot)
                    {
                        parentInstance.SetData(this, null);
                    }

                    creatorLock.Dispose();
                }

                throw;
            }
        }
Beispiel #10
0
        private async ValueTask <IIxInstanceLock> RegistrationScopeBinder(
            IIxInstance originInstance,
            IxResolvePath resolvePath,
            IxResolveContext context,
            [CanBeNull] IxResolveFrame frame,
            IxResolveBoundDelegate resolveBound)
        {
            IIxInstance curInstance = originInstance;

            Critical.Assert(resolvePath.Path.Any(), "Registration scope binder does not support empty path.");

            lock (InstanceTreeSyncRoot)
            {
                while (curInstance != null)
                {
                    if (curInstance.ProviderNode == resolvePath.Root)
                    {
                        break;
                    }

                    curInstance = curInstance.ParentInstance;
                }
            }

            if (curInstance == null)
            {
                throw new InvalidOperationException("Resolve algorithms problems");
            }

            Func <IIxInstance, int, ValueTask <IIxInstanceLock> > resolvePathElements = null;

            resolvePathElements = async(parentInstance, index) =>
            {
                if (index < resolvePath.Path.Count - 1)
                {
                    using (IIxInstanceLock instanceLock = await Resolve(
                               parentInstance,
                               resolvePath.Path[index].Identifier,
                               context,
                               frame))
                    {
                        return(await resolvePathElements(instanceLock.Target, index + 1));
                    }
                }

                return(await resolveBound(parentInstance, resolvePath.Path.Last(), context));
            };

            IIxInstanceLock resultInstanceLock = await resolvePathElements(curInstance, 0);

            return(resultInstanceLock);
        }
Beispiel #11
0
 public abstract ValueTask <IIxInstanceLock> GetInstance(
     IIxInstance parentInstance,
     IxIdentifier identifier,
     IxHost.IxResolveContext context,
     [CanBeNull] IxResolveFrame frame);