public IxResolveFrame( [CanBeNull] IxResolveFrame parentFrame, IIxInstance instance) { ParentFrame = parentFrame; Instance = instance; }
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; }
#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); } }
/// <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)); }
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)); }
/// <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()); } }
public override ValueTask <IIxInstanceLock> GetInstance( IIxInstance parentInstance, IxIdentifier identifier, IxHost.IxResolveContext context, [CanBeNull] IxResolveFrame frame) { throw new NotImplementedException(); }
/// <summary> /// Initializes a new instance of the <see cref="IxScopeInstance"/> class. /// </summary> /// <param name="providerNode">Owner provider.</param> /// <param name="parentInstance">Parent instance.</param> /// <param name="creatorTempLock">First temp lock for the creator of a new instance.</param> public IxScopeInstance( IxProviderNode providerNode, [CanBeNull] IIxInstance parentInstance, out IIxInstanceLock creatorTempLock) : base(providerNode, parentInstance, out creatorTempLock) { SetObjectCreationTask(new ValueTask <object>(providerNode)); }
/// <inheritdoc/> public override async ValueTask <IIxInstanceLock> GetInstance( IIxInstance parentInstance, IxIdentifier identifier, IxHost.IxResolveContext context, [CanBeNull] IxResolveFrame frame) { Critical.Assert(false, "Not supported."); return(null); }
public IxInstanceNoLock(IIxInstance target) { if (target == null) { throw new ArgumentNullException(nameof(target)); } Target = target; }
/// <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; } }
/// <summary> /// Initializes a new instance of the <see cref="IxInstancePinLock"/> class. /// </summary> /// <param name="target">IndirectX instance.</param> public IxInstancePinLock(IIxInstance target) { Critical.Assert(target != null, "Pin lock target should not be null."); Target = target; lock (target.ProviderNode.Host.InstanceTreeSyncRoot) { Target.AddLock(this); } }
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); }
public IxResolveContext( IIxInstance originInstance, [CanBeNull] IxResolveContext parentContext, IReadOnlyDictionary <IxIdentifier, object> arguments) { Critical.CheckedAssert(originInstance != null, "Origin instance should be null."); Critical.CheckedAssert(arguments != null, "Arguments dictionary should not be null."); Arguments = arguments; _originInstance = originInstance; ParentContext = parentContext; _rootContext = parentContext?._rootContext ?? this; Critical.CheckedAssert(_rootContext != null, "Root context should not be null."); }
/// <summary> /// Initializes a new instance of the <see cref="IxInstance"/> class. /// </summary> /// <remarks> /// Instance creates in the "Half-instantiated state". /// </remarks> /// <param name="providerNode">Node that produces instance.</param> /// <param name="parentInstance">Direct parent instance.</param> /// <param name="creatorTempLock">First temp lock for the creator of a new instance.</param> public IxInstance( IxProviderNode providerNode, [CanBeNull] IIxInstance parentInstance, out IIxInstanceLock creatorTempLock) : base(providerNode.Host.InstanceTreeSyncRoot) { ProviderNode = providerNode; _parentInstance = parentInstance; _ownedLocks = new ProcessableSet <IIxInstanceLock>(); _locks = new ProcessableSet <IIxInstanceLock>(); _childrenDisposeCompleted = new AwaitableEvent(); if (parentInstance != null) { new IxInstanceChildLock(parentInstance, this); } creatorTempLock = new IxInstancePinLock(this); _initTempLock = creatorTempLock; }
public IxInstanceChildLock(IIxInstance parent, IIxInstance child) { if (parent == null) { throw new ArgumentNullException(nameof(parent)); } if (child == null) { throw new ArgumentNullException(nameof(child)); } Target = parent; Owner = child; lock (Target.ProviderNode.Host.InstanceTreeSyncRoot) { Target.AddLock(this); Owner.AddOwnedLock(this); } }
/// <summary> /// Initializes a new instance of the <see cref="IxReferenceLock"/> class. /// </summary> /// <param name="target">The instance to lock.</param> /// <param name="owner">The owner of this lock.</param> public IxReferenceLock(IIxInstance target, IIxInstance owner) { if (target == null) { throw new ArgumentNullException(nameof(target)); } if (owner == null) { throw new ArgumentNullException(nameof(owner)); } Critical.Assert(!ReferenceEquals(target, owner), "Cannot create reference from self to self."); Target = target; Owner = owner; lock (Target.ProviderNode.Host.InstanceTreeSyncRoot) { Target.AddLock(this); Owner.AddOwnedLock(this); } }
private ResolveDelegate SelfToChildrenResolver(ResolveDelegate next) { return(async(originInstance, identifier, context, frame) => { if (identifier.Name == null) { IxResolvePath resolvePath; if (originInstance.ProviderNode.VisibleNodes.TryGetValue(identifier, out resolvePath)) { if (!resolvePath.Path.Any()) { lock (InstanceTreeSyncRoot) { IIxInstance curInstance = originInstance; while (curInstance != null) { if (curInstance.ProviderNode == resolvePath.Root) { break; } curInstance = curInstance.ParentInstance; } Critical.Assert( curInstance != null, "Instance of an appropriate provider should be found."); return new IxInstancePinLock(curInstance); } } } } return await next(originInstance, identifier, context, frame); }); }
public abstract ValueTask <IIxInstanceLock> GetInstance( IIxInstance parentInstance, IxIdentifier identifier, IxHost.IxResolveContext context, [CanBeNull] IxResolveFrame frame);