private void uninjectDependency_internal(Type type, int frameStackLevel) { if (!_dependencyStacks.TryGetValue(type, out var stack)) { throw new InjectFrameCloseException( $"No dependency stack for type '{type}' is available.", DisposeExceptionsManager.WrapLastExceptionThrown() ); } if (stack.Count == 0) { throw new InjectFrameCloseException( $"No dependency stack frames for type '{type}' are available.", DisposeExceptionsManager.WrapLastExceptionThrown() ); } StackedDependency toRemove = stack.Peek(); if (toRemove.StackLevel != frameStackLevel) { throw new InjectFrameCloseException( $"Top element of stack for type '{type}' has stack level '{toRemove.StackLevel}' " + $"but frame to be closed has a different stack level: '{frameStackLevel}'.", DisposeExceptionsManager.WrapLastExceptionThrown() ); } markSnapshotDirty(); stack.Pop(); }
// TODO: Ensure that toMatchAgainst isn't a generic type definition, open constructed generic type, // generic type parameter, etc. Or maybe it can be?? private void addToStack_internal(object dependency, Type toMatchAgainst) { var toPush = new StackedDependency(currentStackLevel + 1, dependency); // Must only call RunOnInject() AFTER checking to throw any exceptions. // Must also only call it BEFORE any lasting changes are made, in case it throws an exception. // TODO: Check if there's built-in exceptions that could occur, and check that there's no // possible lasting changes. OutOfMemoryException etc is probably OK, but need to think it through. if (_dependencyStacks.TryGetValue(toMatchAgainst, out var stack)) { if (stack.Peek().StackLevel == currentStackLevel + 1) { throw new InvalidOperationException( $"Cannot inject dependency against type '{toMatchAgainst.FullName}' " + $"as there is already a dependency present against the same type at the current stack level " + $"(stack level = '{currentStackLevel + 1}'). Most likely cause: calling a method to inject multiple " + $"dependencies at the same time (i.e. at the same stack level), but requesting to add two or " + $"more dependencies against the same type, or more than one wildcard dependency. This would " + $"result in an ambiguity for what object should be returned when the dependencies are fetched " + $"(in the case of wildcards, attempting to fetch a dependency against type 'object' or any other " + $"common parent type would cause this ambiguity). Instead, this is disallowed. Consider " + $"injecting the dependencies one at a time so that they have a defined priority order. " + $"Otherwise, if you do need multiple of the same dependency type T to be fetched as a group, " + $"consider using Inject() and Fetch() with a T[], List<T>, or some other collection. If you need " + $"inner code to both Fetch() the group and Fetch() just the first element (for example) then inject" + $"e.g. both the List<T> and the instance of T." ); } toPush.RunOnInject(); markSnapshotDirty(); stack.Push(toPush); } else { toPush.RunOnInject(); markSnapshotDirty(); _dependencyStacks.Add(toMatchAgainst, new SearchableStack <StackedDependency> { toPush }); } }