internal InjectFrame(DependencyLayer layer, int parentStackLevel, Type type) { if (parentStackLevel < 0) { throw new ArgumentOutOfRangeException(nameof(parentStackLevel), "Cannot be negative."); } this.layer = layer ?? throw new ArgumentNullException(nameof(layer)); this.parentStackLevel = parentStackLevel; this.type = type ?? throw new ArgumentNullException(nameof(type)); this._disposed = false; }
public override bool TryFetch <T>(out T dependency, bool useFallbacks) => _stack.Peek().dependencies.TryGetValue(typeof(T), out StackedDependency dep) ? Logic.SucceedIf( !dep.IsNull, out dependency, (T)dep.Dependency ) : useFallbacks ? Logic.SucceedIf(DependencyLayer.TryFetch( this.Fallback, out dependency, useFallbacks )) : Logic.Fail(out dependency);
private static bool isParentOfLayer(DependencyLayer parent, DependencyLayer child) { var l = child; while (l != null) { if (l == parent) { return(true); } l = l.Fallback; } return(false); }
internal static void CloseLayer(DependencyLayer layer) { if (layer != CurrentLayer) { LayerCloseMismatch?.Invoke(null, new LayerCloseErrorEventArgs(CurrentLayer, layer)); } if (layer.Fallback == null) { // TODO: Fix that in the case of fallbacks being modified via reflection, this error message won't make sense throw new InvalidDIStateException( "Cannot close root dependency layer (Fallback == null).", DisposeExceptionsManager.WrapLastExceptionThrown() ); } if (!isParentOfLayer(layer, CurrentLayer)) { // Layers are only created and added to the fallback-stack by calling NewLayer(), // and only removed by calling CloseLayer() via Dispose(), which only runs once. // If a layer has been added, and has not yet been disposed/closed, then it must be // possible to find it. // So if we failed to find it, reflection must have been used to either create a // layer without adding it, or used to modify the fallback of a layer. // Someones done that, throw an exception // TODO: Fix that in the case of fallbacks being modified via reflection, this error message won't make sense throw new InvalidDIStateException( $"{nameof(MutatingDependencyLayer)} '{layer}' was never opened.", DisposeExceptionsManager.WrapLastExceptionThrown() ); } // Now that we know it's safe to do so (we will eventually hit the layer to close), // step up from the current layer, marking each layer closed as we go, until we reach // the layer to close, and close it. var l = CurrentLayer; while (l != null) { if (l == layer) { l.MarkDisposed(); // just in case _currentLayer = l.Fallback; // close all layers below l.Fallback return; } l.MarkDisposed(); l = l.Fallback; } }
public override DependencySnapshot Snapshot(bool useFallbacks) { if (SnapshotReady) { return(_snapshot); } var builder = ImmutableDictionary.CreateBuilder <Type, StackedDependency>(); builder.AddRange(enumerateDependencies()); IEnumerable <KeyValuePair <Type, StackedDependency> > enumerateDependencies() { foreach (var kvp in _dependencyStacks) { if (kvp.Value.Count != 0) { yield return(new KeyValuePair <Type, StackedDependency>( kvp.Key, kvp.Value.Peek().RunOnSnapshot() )); } } } var fb = this.Fallback; while (useFallbacks && fb != null) { DependencyLayer.AddAsFallbackToSnapshot(fb, builder); fb = fb.Fallback; } return(_snapshot = new DependencySnapshot(builder.ToImmutable())); }
internal DependencyLayer(DependencyLayer fallback) { this.Fallback = fallback ?? throw new ArgumentNullException(nameof(fallback)); }
private protected static void AddAsFallbackToSnapshot( DependencyLayer fallback, ImmutableDictionary <Type, StackedDependency> .Builder snapshotBuilder ) => fallback.AddAsFallbackToSnapshot(snapshotBuilder);
internal Disposer(DependencyLayer layer) => this.Layer = layer;
internal SafeDependencyLayer(DependencyLayer fallback) : base(fallback) { }
public static DependencyLayer.Disposer NewLayer() { _currentLayer = new MutatingDependencyLayer(fallback: CurrentLayer); return(new DependencyLayer.Disposer(_currentLayer)); }
internal MutatingDependencyLayer(DependencyLayer fallback) : base(fallback) { }
public LayerCloseErrorEventArgs(DependencyLayer currentLayer, DependencyLayer layerToClose) { this.CurrentLayer = currentLayer; this.LayerToClose = layerToClose; }