/// <summary> /// Given a StorageInfoCore, clears the enumerators associated with it. /// </summary> private static void InvalidateEnumerators( StorageInfoCore invalidateCore ) { // It is not enough to simply clear the validEnumerators collection, // we have to clear the individual elements to let them know the // outstanding enumerator is no longer valid. foreach( object entry in invalidateCore.validEnumerators.Values ) { ((ArrayList)entry).Clear(); } invalidateCore.validEnumerators.Clear(); }
/// <summary> /// Respond to a request from a child StorageInfo object to give /// it a StorageInfoCore object for the given name. /// </summary> StorageInfoCore CoreForChildStorage( string storageNname ) { CheckDisposedStatus(); object childElement = core.elementInfoCores[ storageNname ]; if( null != childElement && null == childElement as StorageInfoCore ) { // Name is already in use, but not as a StorageInfo throw new InvalidOperationException( SR.Get(SRID.NameAlreadyInUse, storageNname )); } else if( null == childElement ) { // No such element with the name exist - create one. // childElement = new StorageInfoCore( storageNname); core.elementInfoCores[ storageNname ] = childElement; } Debug.Assert( null != childElement as StorageInfoCore, "We should have already checked to make sure childElement is either StorageInfoCore, created as one, or thrown an exception if neither is possible"); return childElement as StorageInfoCore; }
/***********************************************************************/ // Constructors /// <summary> /// A constructor for building the root storage. /// This should only happen for, well, the root storage! /// </summary> internal StorageInfo( IStorage safeIStorage ) { core = new StorageInfoCore( null, safeIStorage ); }
/// <summary> /// Given a parent and a path under it, step through each of the path /// elements and create an intermediate StorageInfo at each step because /// a StorageInfo is only meaningful relative to its immediate parent - /// multi-step relations can't be represented. /// </summary> private void BuildStorageInfoRelativeToStorage( StorageInfo parent, string fileName ) { parentStorage = parent; core = parent.CoreForChildStorage( fileName ); rootStorage = parent.Root; }
/// <summary> /// Given a StorageInfoCore, recursively release objects associated with /// sub-storages and then releases objects associated with self. /// </summary> /// <remarks> /// This didn't used to be a static method - but this caused some problems. /// All operations need to be on the given parameter "startCore". If this /// wasn't static, the code had access to the member "core" and that's not /// the right StorageInfoCore to use. This caused some bugs that would have /// been avoided if this was static. To prevent future bugs of similar /// nature, I made this static. /// </remarks> internal static void RecursiveStorageInfoCoreRelease( StorageInfoCore startCore ) { // If the underlying IStorage pointer is null, we never did anything // with this storage or anything under it. We can halt our recursion // here. if( startCore.safeIStorage == null ) return; try { ////////////////////////////////////////////////////////////////////// // // Call clean-up code for things on the storage represented by startCore. ////////////////////////////////////////////////////////////////////// // // Call clean-up code for things *under* startCore. // See if we have child storages and streams, and if so, close them // down. foreach( object o in startCore.elementInfoCores.Values ) { if( o is StorageInfoCore ) { RecursiveStorageInfoCoreRelease( (StorageInfoCore)o ); } else if( o is StreamInfoCore ) { StreamInfoCore streamRelease = (StreamInfoCore)o; try { if (null != streamRelease.exposedStream) { ((Stream)(streamRelease.exposedStream)).Close(); } streamRelease.exposedStream = null; } finally { // We need this release and null-out to happen even if we // ran into problems with the clean-up code above. if( null != streamRelease.safeIStream) { ((IDisposable) streamRelease.safeIStream).Dispose(); streamRelease.safeIStream = null; } // Null name in core signifies the core object is disposed ((StreamInfoCore)o).streamName = null; } } } // All child objects freed, clear out the enumerators InvalidateEnumerators( startCore ); } finally { // We want to make sure this happens even if any of the cleanup // above fails, so that's why it's in a "finally" block here. ////////////////////////////////////////////////////////////////////// // // Free unmanaged resources associated with the startCore storage if( null != startCore.safeIStorage) { ((IDisposable) startCore.safeIStorage).Dispose(); startCore.safeIStorage = null; } // Null name in core signifies the core object is disposed startCore.storageName = null; } }