//------------------------------------------------------------------------- // Protected Methods - Package Overrides //------------------------------------------------------------------------- /// <summary> /// Creates a new PackagePart. /// </summary> /// <remarks> /// When creating a new PackagePart we must: /// a) ensure the part does not exist in package /// b) ensure there is a writable package /// c) create a temp part /// d) update active part reference to the temp part /// /// What if a PackagePart with the same Uri already exists? /// Package.CreatePart checks for this. /// /// Do we need to worry about updating relationships and other parts? /// Relationships are a part and are thus intrinsically handled. /// </remarks> /// <param name="partUri">Uri for the part to create.</param> /// <param name="contentType">Content type string.</param> /// <param name="compressionOption">Compression options.</param> /// <returns>A new PackagePart.</returns> protected override PackagePart CreatePartCore( Uri partUri, string contentType, CompressionOption compressionOption) { // Skipping parameter validation as it is done by CreatePart. EnsureTempPackage(); // the underlying temp package does all the physical work PackagePart result = _tempPackage.Value.CreatePart( partUri, contentType, compressionOption); Uri normalizedPartUri = PackUriHelper.GetNormalizedPartUri(partUri); result = new WriteableOnDemandPackagePart( this, result, TempPackagePartFactory); _activeParts.Add(normalizedPartUri, (WriteableOnDemandPackagePart)result); Trace.SafeWrite( Trace.Packaging, "New part {0}({1})#{2} created.", result.Uri, result.ContentType, result.GetHashCode()); return(result); }
/// <summary> /// Returns an existing PackagePart. /// </summary> /// <remarks> /// When getting an existing PackagePart we must: /// a) Create a proxy (WriteableOnDemandPackagePart) if there is not /// already one; if there is we just return it. /// b) We must return the same instance of the proxy for any request /// for that part, as new instances will not have any way of /// knowing which internal part is 'active' (original/temp) within /// the proxy. /// /// What if the part does not exist? /// What if the part has been deleted? /// These cases are handled by Package.GetPart. /// /// What if the part ends up being edited? /// That is the reason for the proxy, on edit the internal reference /// will be updated to the temp object and it will service the call. /// /// What if a part has already been edited? /// That is why we must return the active part. /// </remarks> /// <param name="partUri">The Uri of the part to return.</param> /// <returns>An existing PackagePart.</returns> protected override PackagePart GetPartCore(Uri partUri) { // Skipping parameter validation as it is done by CreatePart. PackagePart result = null; Uri normalizedPartUri = PackUriHelper.GetNormalizedPartUri(partUri); #if DEBUG if (_activeParts.ContainsKey(normalizedPartUri)) { Trace.SafeWrite( Trace.Packaging, "WARNING: GetPartCore called multiple times for {0}.", partUri); } #endif // We can get the part from three places, which we check in this order: // 1) Our saved list of active parts. It's important to get it from // here if possible because all references should point to a single // instance of our WriteableOnDemandPackagePart class. // 2) The temp package. If there is a change to a part it will be here, // and we want to return the user's changes. // 3) The original package. // Even if the part exists in our list of active parts, as part of our // contract with the Packaging team we still must use PartExists to // check if the part is actually present in either the temporary or the // original package. If the part does not exist in either the original // or the temporary package, this method will return null. bool canGetFromTempPackage = (_tempPackage.Value != null) && (_tempPackage.Value.PartExists(partUri)); bool canGetFromOriginalPackage = canGetFromTempPackage ? false : _originalPackage.Value.PartExists(partUri); if (_activeParts.ContainsKey(normalizedPartUri) && (canGetFromTempPackage || canGetFromOriginalPackage)) { result = _activeParts[normalizedPartUri]; } else if (canGetFromTempPackage) { result = _tempPackage.Value.GetPart(partUri); result = new WriteableOnDemandPackagePart( this, result, TempPackagePartFactory); _activeParts.Add(normalizedPartUri, (WriteableOnDemandPackagePart)result); Trace.SafeWrite( Trace.Packaging, "GetPartCore returned {0}({1})#{2} a temp part.", partUri, result.ContentType, result.GetHashCode()); } else if (canGetFromOriginalPackage) { PackagePart original = _originalPackage.Value.GetPart(partUri); result = new WriteableOnDemandPackagePart( this, original, TempPackagePartFactory); _activeParts.Add(normalizedPartUri, (WriteableOnDemandPackagePart)result); Trace.SafeWrite( Trace.Packaging, "GetPartCore returned {0}({1})#{2} a new proxy.", partUri, result.ContentType, result.GetHashCode()); } return(result); }