예제 #1
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));
        }
예제 #2
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);
            }
        }
예제 #3
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());
            }
        }
예제 #4
0
 public override ValueTask <IIxInstanceLock> GetInstance(
     IIxInstance parentInstance,
     IxIdentifier identifier,
     IxHost.IxResolveContext context,
     [CanBeNull] IxResolveFrame frame)
 {
     throw new NotImplementedException();
 }
예제 #5
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);
 }
예제 #6
0
        /// <summary>
        /// Initializes a new instance of the <see cref="IxResolveTargetNotFound"/> class with a specified error message and inner
        /// exception.
        /// </summary>
        /// <param name="message">The message that describes the error. </param>
        /// <param name="identifier">Resolve target identifier.</param>
        /// <param name="innerException">Inner error.</param>
        public IxResolveTargetNotFound(string message, IxIdentifier identifier, Exception innerException)
            : base(message, innerException)
        {
            if (identifier == default(IxIdentifier))
            {
                throw new ArgumentException("Identifier should not be empty.", nameof(identifier));
            }

            Identifier = identifier;
        }
예제 #7
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;
            }
        }
예제 #8
0
            public async ValueTask <IIxInstanceLock> Resolve(
                IxIdentifier identifier,
                IReadOnlyDictionary <IxIdentifier, object> arguments = null)
            {
                var context = new IxResolveContext(
                    OwnerInstance,
                    ParentContext,
                    arguments ?? new Dictionary <IxIdentifier, object>());

                using (new IxInstancePinLock(OwnerInstance))
                {
                    return(await Host.Resolve(OwnerInstance, identifier, context, ParentFrame));
                }
            }
예제 #9
0
        /// <summary>
        /// Tries to get argument value for the provided identifier.
        /// </summary>
        /// <param name="identifier">Argument identifier.</param>
        /// <param name="context">The resolve context.</param>
        /// <returns>Argument instance lock or null, if no argument found for the provided identifier.</returns>
        public IIxInstanceLock TryGetInstance(IxIdentifier identifier, IxHost.IxResolveContext context)
        {
            IxHost.IxResolveContext curContext = context;
            while (curContext != null)
            {
                if (context.Arguments.TryGetValue(identifier, out var result))
                {
                    return(new IxInstancePinLock(new IxArgumentInstance(this, result)));
                }

                curContext = context.ParentContext;
            }

            // ReSharper disable once AssignNullToNotNullAttribute
            return(null);
        }
예제 #10
0
 public abstract ValueTask <IIxInstanceLock> GetInstance(
     IIxInstance parentInstance,
     IxIdentifier identifier,
     IxHost.IxResolveContext context,
     [CanBeNull] IxResolveFrame frame);