Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Base / System / IO / Packaging / PackagePart.cs / 1 / PackagePart.cs
//------------------------------------------------------------------------------ // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // Description: // This is a base abstract class for PackagePart. This is a part of the // Packaging Layer // // History: // 01/03/2004: SarjanaS: Initial creation. [Stubs Only] // 03/01/2004: SarjanaS: Implemented the functionality for all the members. // 03/17/2004: BruceMac: Initial implementation or PackageRelationship methods // //----------------------------------------------------------------------------- using System; using System.IO; using System.Collections; using System.Windows; // For Exception strings - SRID using System.Collections.Generic; // For List <> using MS.Internal.IO.Packaging; using System.Diagnostics; // For Debug.Assert using MS.Internal; // For Invariant.Assert #pragma warning disable 1634, 1691 // suppressing PreSharp warnings namespace System.IO.Packaging { ////// This class represents the a PackagePart within a container. /// This is a part of the Packaging Layer APIs /// public abstract class PackagePart { //----------------------------------------------------- // // Public Constructors // //----------------------------------------------------- #region Protected Constructor ////// Protected constructor for the abstract Base class. /// This is the current contract between the subclass and the base class /// If we decide some registration mechanism then this might change /// /// You should use this constructor in the rare case when you do not have /// the content type information related to this part and would prefer to /// obtain it later as required. /// /// These parts have the CompressionOption as NotCompressed by default. /// /// NOTE : If you are using this constructor from your subclass or passing a null /// for the content type parameter, be sure to implement the GetContentTypeCore /// method, as that will be called to get the content type value. This is provided /// to enable lazy initialization of the ContentType property. /// /// /// Package in which this part is being created /// uri of the part ///If parameter "package" is null ///If parameter "partUri" is null protected PackagePart(Package package, Uri partUri) :this(package, partUri, null, CompressionOption.NotCompressed) { } ////// Protected constructor for the abstract Base class. /// This is the current contract between the subclass and the base class /// If we decide some registration mechanism then this might change /// /// These parts have the CompressionOption as NotCompressed by default. /// /// NOTE : If you are using this constructor from your subclass or passing a null /// for the content type parameter, be sure to implement the GetContentTypeCore /// method, as that will be called to get the content type value. This is provided /// to enable lazy initialization of the ContentType property. /// /// /// Package in which this part is being created /// uri of the part /// Content Type of the part, can be null if the value /// is unknown at the time of construction. However the value has to be made /// available anytime the ContentType property is called. A null value only indicates /// that the value will be provided later. Every PackagePart must have a valid /// Content Type ///If parameter "package" is null ///If parameter "partUri" is null ///If parameter "partUri" does not conform to the valid partUri syntax protected PackagePart(Package package, Uri partUri, string contentType) :this(package, partUri, contentType, CompressionOption.NotCompressed) { } ////// Protected constructor for the abstract Base class. /// This is the current contract between the subclass and the base class /// If we decide some registration mechanism then this might change /// /// NOTE : If you are using this constructor from your subclass or passing a null /// for the content type parameter, be sure to implement the GetContentTypeCore /// method, as that will be called to get the content type value. This is provided /// to enable lazy initialization of the ContentType property. /// /// /// Package in which this part is being created /// uri of the part /// Content Type of the part, can be null if the value /// is unknown at the time of construction. However the value has to be made /// available anytime the ContentType property is called. A null value only indicates /// that the value will be provided later. Every PackagePart must have a valid /// Content Type /// compression option for this part ///If parameter "package" is null ///If parameter "partUri" is null ///If CompressionOption enumeration [compressionOption] does not have one of the valid values ///If parameter "partUri" does not conform to the valid partUri syntax protected PackagePart(Package package, Uri partUri, string contentType, CompressionOption compressionOption) { if (package == null) throw new ArgumentNullException("package"); if (partUri == null) throw new ArgumentNullException("partUri"); Package.ThrowIfCompressionOptionInvalid(compressionOption); _uri = PackUriHelper.ValidatePartUri(partUri); _container = package; if (contentType == null) _contentType = null; else _contentType = new ContentType(contentType); _requestedStreams = null; _compressionOption = compressionOption; _isRelationshipPart = PackUriHelper.IsRelationshipPartUri(partUri); } #endregion Protected Constructor //------------------------------------------------------ // // Public Properties // //----------------------------------------------------- #region Public Properties ////// The Uri for this PackagePart. It is always relative to the Package Root /// The PackagePart properties can not be accessed if the parent container is closed. /// ////// If this part has been deleted ///If the parent package has been closed or disposed public Uri Uri { get { CheckInvalidState(); return _uri; } } ////// The Content type of the stream that is represented by this part. /// The PackagePart properties can not be accessed if the parent container is closed. /// The content type value can be provided by the underlying physical format /// implementation at the time of creation of the Part object ( constructor ) or /// We can initialize it in a lazy manner when the ContentType property is called /// called for the first time by calling the GetContentTypeCore method. /// Note: This method GetContentTypeCore() is only for lazy initialization of the Content /// type value and will only be called once. There is no way to change the content type of /// the part once it has been assigned. /// ///Content Type of the Part [can never return null] ///If this part has been deleted ///If the parent package has been closed or disposed ///If the subclass fails to provide a non-null content type value. public string ContentType { get { CheckInvalidState(); if (_contentType == null) { //Lazy initialization for the content type string contentType = GetContentTypeCore(); if (contentType == null) { // From sarjanas: // // We have seen this bug in the past and have said that this should be // treated as exception. If we get a null content type, it’s an error. // We want to throw this exception so that anyone sub-classing this class // should not be setting the content type to null. Its like any other // parameter validation. This is the only place we can validate it. We // throw an ArgumentNullException, when the content type is set to null // in the constructor. // // We cannot get rid of this exception. At most, we can change it to // Invariant.Assert. But then client code will see an Assert if they make // a mistake and that is also not desirable. // // PackagePart is a public API. #pragma warning suppress 6503 throw new InvalidOperationException(SR.Get(SRID.NullContentTypeProvided)); } _contentType = new ContentType(contentType); } return _contentType.ToString(); } } ////// The parent container for this PackagePart /// The PackagePart properties can not be accessed if the parent container is closed. /// ////// If this part has been deleted ///If the parent package has been closed or disposed public Package Package { get { CheckInvalidState(); return _container; } } ////// CompressionOption class that was provided as a parameter during the original CreatePart call. /// The PackagePart properties can not be accessed if the parent container is closed. /// ///If this part has been deleted ///If the parent package has been closed or disposed public CompressionOption CompressionOption { get { CheckInvalidState(); return _compressionOption; } } #endregion Public Properties //------------------------------------------------------ // // Public Methods // //------------------------------------------------------ #region Public Methods #region Content Type Method ////// Custom Implementation for the GetContentType Method /// This method should only be implemented by those physical format implementors where /// the value for the content type cannot be provided at the time of construction of /// Part object and if calculating the content type value is a non-trivial or costly /// operation. The return value has to be a valid ContentType. This method will be used in /// real corner cases. The most common usage should be to provide the content type in the /// constructor. /// This method is only for lazy initialization of the Content type value and will only /// be called once. There is no way to change the content type of the part once it is /// assigned. /// ///Content type for the Part ///By default, this method throws a NotSupportedException. If a subclass wants to /// initialize the content type for a PackagePart in a lazy manner they must override this method. protected virtual string GetContentTypeCore() { throw new NotSupportedException(SR.Get(SRID.GetContentTypeCoreNotImplemented)); } #endregion Content Type Method #region Stream Methods ////// Returns the underlying stream that is represented by this part /// with the default FileMode and FileAccess /// Note: If you are requesting a stream for a relationship part and /// at the same time using relationship APIs to manipulate relationships, /// the final persisted data will depend on which data gets flushed last. /// ////// If this part has been deleted ///If the parent package has been closed or disposed ///If the subclass fails to provide a non-null stream object public Stream GetStream() { CheckInvalidState(); return GetStream(FileMode.OpenOrCreate, _container.FileOpenAccess); } ////// Returns the underlying stream in the specified mode and the /// default FileAccess /// Note: If you are requesting a stream for a relationship part for editing /// and at the same time using relationship APIs to manipulate relationships, /// the final persisted data will depend on which data gets flushed last. /// /// ////// If this part has been deleted ///If the parent package has been closed or disposed ///If FileMode enumeration [mode] does not have one of the valid values ///If FileAccess.Read is provided and FileMode values are any of the following - /// FileMode.Create, FileMode.CreateNew, FileMode.Truncate, FileMode.Append ///If the mode and access for the Package and the Stream are not compatible ///If the subclass fails to provide a non-null stream object public Stream GetStream(FileMode mode) { CheckInvalidState(); return GetStream(mode, _container.FileOpenAccess); } ////// Returns the underlying stream that is represented by this part /// in the specified mode with the access. /// Note: If you are requesting a stream for a relationship part and /// at the same time using relationship APIs to manipulate relationships, /// the final persisted data will depend on which data gets flushed last. /// /// /// ////// If this part has been deleted ///If the parent package has been closed or disposed ///If FileMode enumeration [mode] does not have one of the valid values ///If FileAccess enumeration [access] does not have one of the valid values ///If FileAccess.Read is provided and FileMode values are any of the following - /// FileMode.Create, FileMode.CreateNew, FileMode.Truncate, FileMode.Append ///If the mode and access for the Package and the Stream are not compatible ///If the subclass fails to provide a non-null stream object public Stream GetStream(FileMode mode, FileAccess access) { CheckInvalidState(); ThrowIfOpenAccessModesAreIncompatible(mode, access); Stream s = GetStreamCore(mode, access); if (s == null) throw new IOException(SR.Get(SRID.NullStreamReturned)); //Detect if any stream implementations are returning all three //properties - CanSeek, CanWrite and CanRead as false. Such a //stream should be pretty much useless. And as per current programming //practice, these properties are all false, when the stream has been //disposed. Debug.Assert(!IsStreamClosed(s)); //Lazy init if(_requestedStreams==null) _requestedStreams = new List(); //Default capacity is 4 //Delete all the closed streams from the _requestedStreams list. //Each time a new stream is handed out, we go through the list //to clean up streams that were handed out and have been closed. //Thus those stream can be garbage collected and we will avoid //keeping around stream objects that have been disposed CleanUpRequestedStreamsList(); _requestedStreams.Add(s); return s; } /// /// Custom Implementation for the GetSream Method /// /// /// ///protected abstract Stream GetStreamCore(FileMode mode, FileAccess access); #endregion Stream Methods #region PackageRelationship Methods /// /// Adds a relationship to this PackagePart with the Target PackagePart specified as the Uri /// Initial and trailing spaces in the name of the PackageRelationship are trimmed. /// /// /// Enumeration indicating the base uri for the target uri /// PackageRelationship type, having uri like syntax that is used to /// uniquely identify the role of the relationship ////// If this part has been deleted ///If the parent package has been closed or disposed ///If the package is readonly, it cannot be modified ///If parameter "targetUri" is null ///If parameter "relationshipType" is null ///If parameter "targetMode" enumeration does not have a valid value ///If TargetMode is TargetMode.Internal and the targetUri is an absolute Uri ///If relationship is being targeted to a relationship part public PackageRelationship CreateRelationship(Uri targetUri, TargetMode targetMode, string relationshipType) { return CreateRelationship(targetUri, targetMode, relationshipType, null); } ////// Adds a relationship to this PackagePart with the Target PackagePart specified as the Uri /// Initial and trailing spaces in the name of the PackageRelationship are trimmed. /// /// /// Enumeration indicating the base uri for the target uri /// PackageRelationship type, having uri like syntax that is used to /// uniquely identify the role of the relationship /// String that conforms to the xsd:ID datatype. Unique across the source's /// relationships. Null is OK (ID will be generated). An empty string is an invalid XML ID. ////// If this part has been deleted ///If the parent package has been closed or disposed ///If the package is readonly, it cannot be modified ///If parameter "targetUri" is null ///If parameter "relationshipType" is null ///If parameter "targetMode" enumeration does not have a valid value ///If TargetMode is TargetMode.Internal and the targetUri is an absolute Uri ///If relationship is being targeted to a relationship part ///If parameter "id" is not a valid Xsd Id ///If an id is provided in the method, and its not unique public PackageRelationship CreateRelationship(Uri targetUri, TargetMode targetMode, string relationshipType, String id) { CheckInvalidState(); _container.ThrowIfReadOnly(); EnsureRelationships(); //All parameter validation is done in the following method return _relationships.Add(targetUri, targetMode, relationshipType, id); } ////// Deletes a relationship from the PackagePart. This is done based on the /// relationship's ID. The target PackagePart is not affected by this operation. /// /// The ID of the relationship to delete. An invalid ID will not /// throw an exception, but nothing will be deleted. ///If this part has been deleted ///If the parent package has been closed or disposed ///If the package is readonly, it cannot be modified ///If parameter "id" is null ///If parameter "id" is not a valid Xsd Id public void DeleteRelationship(string id) { CheckInvalidState(); _container.ThrowIfReadOnly(); _container.ThrowIfInStreamingCreation("DeleteRelationship"); if (id == null) throw new ArgumentNullException("id"); InternalRelationshipCollection.ThrowIfInvalidXsdId(id); EnsureRelationships(); _relationships.Delete(id); } ////// Returns a collection of all the Relationships that are /// owned by this PackagePart /// ////// If this part has been deleted ///If the parent package has been closed or disposed ///If the package is write only, no information can be retrieved from it public PackageRelationshipCollection GetRelationships() { //All the validations for dispose and file access are done in the //GetRelationshipsHelper method. return GetRelationshipsHelper(null); } ////// Returns a collection of filtered Relationships that are /// owned by this PackagePart /// The relationshipType string is compared with the type of the relationships /// in a case sensitive and culture ignorant manner. /// ////// If this part has been deleted ///If the parent package has been closed or disposed ///If the package is write only, no information can be retrieved from it ///If parameter "relationshipType" is null ///If parameter "relationshipType" is an empty string public PackageRelationshipCollection GetRelationshipsByType(string relationshipType) { //These checks are made in the GetRelationshipsHelper as well, but we make them //here as we need to perform parameter validation CheckInvalidState(); _container.ThrowIfWriteOnly(); if (relationshipType == null) throw new ArgumentNullException("relationshipType"); InternalRelationshipCollection.ThrowIfInvalidRelationshipType(relationshipType); return GetRelationshipsHelper(relationshipType); } ////// Retrieve a relationship per ID. /// /// The relationship ID. ///The relationship with ID 'id' or throw an exception if not found. ///If this part has been deleted ///If the parent package has been closed or disposed ///If the package is write only, no information can be retrieved from it ///If parameter "id" is null ///If parameter "id" is not a valid Xsd Id ///If the requested relationship does not exist in the Package public PackageRelationship GetRelationship(string id) { //All the validations for dispose and file access are done in the //GetRelationshipHelper method. PackageRelationship returnedRelationship = GetRelationshipHelper(id); if (returnedRelationship == null) throw new InvalidOperationException(SR.Get(SRID.PackagePartRelationshipDoesNotExist)); else return returnedRelationship; } ////// Returns whether there is a relationship with the specified ID. /// /// The relationship ID. ///true iff a relationship with ID 'id' is defined on this source. ///If this part has been deleted ///If the parent package has been closed or disposed ///If the package is write only, no information can be retrieved from it ///If parameter "id" is null ///If parameter "id" is not a valid Xsd Id public bool RelationshipExists(string id) { //All the validations for dispose and file access are done in the //GetRelationshipHelper method. return (GetRelationshipHelper(id) != null); } #endregion PackageRelationship Methods #endregion Public Methods //----------------------------------------------------- // // Public Events // //------------------------------------------------------ // None //----------------------------------------------------- // // Internal Constructors // //----------------------------------------------------- // None //----------------------------------------------------- // // Internal Properties // //------------------------------------------------------ #region Internal Properties internal bool IsRelationshipPart { get { return _isRelationshipPart; } } //This property can be set to indicate if the part has been deleted internal bool IsDeleted { get { return _deleted; } set { _deleted = value; } } //This property can be set to indicate if the part has been deleted internal bool IsClosed { get { return _disposed; } } ////// This property returns the content type of the part /// as a validated strongly typed ContentType object /// internal ContentType ValidatedContentType { get { return _contentType; } } #endregion Internal Properties //----------------------------------------------------- // // Internal Methods // //------------------------------------------------------ #region Internal Methods //Delete all the relationships for this part internal void ClearRelationships() { if(_relationships!=null) _relationships.Clear(); } //Flush all the streams that are currently opened for this part and the relationships for this part //Note: This method is never be called on a deleted part internal void Flush() { Debug.Assert(_deleted != true, "PackagePart.Flush should never be called on a deleted part"); if (_requestedStreams!= null) { foreach (Stream s in _requestedStreams) { // Streams in this list are never set to null, so we do not need to check for // stream being null; However it could be closed by some external code. In that case // this property (CanWrite) will still be accessible and we can check to see // whether we can call flush or no. if (s.CanWrite) s.Flush(); } } // Relationships for this part should have been flushed earlier in the Package.Flush method. } //Close all the streams that are open for this part. internal void Close() { if (!_disposed) { try { if (_requestedStreams != null) { //Adding this extra check here to optimize delete operation //Everytime we delete a part we close it before deleting to //ensure that its deleted in a valid state. However, we do not //need to persist any changes if the part is being deleted. if (!_deleted) { foreach (Stream s in _requestedStreams) { s.Close(); } } _requestedStreams.Clear(); } // In streaming creation, if the part has had no stream opened on it, // it has not been physically added to the archive yet. else if (_container.InStreamingCreation) { // Create an interleaving stream to make sure a physical item gets created. GetStream(FileMode.CreateNew, _container.FileOpenAccess).Close(); } // Relationships for this part should have been flushed/closed earlier in the Package.Close method. } finally { _requestedStreams = null; //InternalRelationshipCollection is not required any more _relationships = null; //Once the container is closed there is no way to get to the stream or any other part //in the container. _container = null; //We do not need to explicitly call GC.SuppressFinalize(this) _disposed = true; } } } #region Write-Time Streaming API ////// According to the access mode (streaming or not), /// write the whole relationships part or just a nonterminal /// nonterminal piece for the relationships part. /// ////// The behavior of _relationships.Flush, which gets invoked here, will vary /// according as the package was opened for streaming production or not. /// internal void FlushRelationships() { Debug.Assert(_deleted != true, "PackagePart.FlushRelationsips should never be called on a deleted part"); // flush relationships if (_relationships != null && _container.FileOpenAccess != FileAccess.Read) { _relationships.Flush(); } } internal void CloseRelationships() { if (!_deleted) { //Flush the relationships for this part. if (_container.InStreamingCreation) { // Flush unsaved relationships, // close XML markup and save as the last piece. CloseStreamingRelationships(); } else { FlushRelationships(); } } } ////// Write a terminal piece for folderPath/_rels/baseName.rels /// private void CloseStreamingRelationships() { if (!_container.InStreamingCreation) throw new IOException(SR.Get(SRID.MethodAvailableOnlyInStreamingCreation, "CloseRelationships")); if (_relationships == null) return; // No relationship has been created. _relationships.CloseInStreamingCreationMode(); } #endregion Write-Time Streaming API #endregion Internal Methods //------------------------------------------------------ // // Internal Events // //----------------------------------------------------- // None //------------------------------------------------------ // // Private Methods // //----------------------------------------------------- #region Private Methods // lazy init private void EnsureRelationships() { if (_relationships == null) { // check here ThrowIfRelationship(); // obtain the relationships from the PackageRelationship part (if available) _relationships = new InternalRelationshipCollection(this); } } //Make sure that the access modes for the container and the part are compatible private void ThrowIfOpenAccessModesAreIncompatible(FileMode mode, FileAccess access) { Package.ThrowIfFileModeInvalid(mode); Package.ThrowIfFileAccessInvalid(access); //Creating a part using a readonly stream. if(access == FileAccess.Read && (mode == FileMode.Create || mode == FileMode.CreateNew || mode == FileMode.Truncate || mode == FileMode.Append)) throw new IOException(SR.Get(SRID.UnsupportedCombinationOfModeAccess)); //Incompatible access modes between container and part stream. if((_container.FileOpenAccess == FileAccess.Read && access != FileAccess.Read) || (_container.FileOpenAccess == FileAccess.Write && access != FileAccess.Write) ) throw new IOException(SR.Get(SRID.ContainerAndPartModeIncompatible)); } //Check if the part is in an invalid state private void CheckInvalidState() { ThrowIfPackagePartDeleted(); ThrowIfParentContainerClosed(); } //If the parent container is closed then the operations on this part like getting stream make no sense private void ThrowIfParentContainerClosed() { if (_container == null) throw new InvalidOperationException(SR.Get(SRID.ParentContainerClosed)); } //If the part has been deleted then we throw private void ThrowIfPackagePartDeleted() { if (_deleted == true) throw new InvalidOperationException(SR.Get(SRID.PackagePartDeleted)); } // some operations are invalid if we are a relationship part private void ThrowIfRelationship() { if (IsRelationshipPart) throw new InvalidOperationException(SR.Get(SRID.RelationshipPartsCannotHaveRelationships)); } ////// Retrieve a relationship per ID. /// /// The relationship ID. ///The relationship with ID 'id' or null if not found. private PackageRelationship GetRelationshipHelper(string id) { CheckInvalidState(); _container.ThrowIfWriteOnly(); if (id == null) throw new ArgumentNullException("id"); InternalRelationshipCollection.ThrowIfInvalidXsdId(id); EnsureRelationships(); return _relationships.GetRelationship(id); } ////// Returns a collection of all the Relationships that are /// owned by this PackagePart, based on the filter string /// ///private PackageRelationshipCollection GetRelationshipsHelper(string filterString) { CheckInvalidState(); _container.ThrowIfWriteOnly(); EnsureRelationships(); //Internally null is used to indicate that no filter string was specified and //and all the relationships should be returned. return new PackageRelationshipCollection(_relationships, filterString); } //Deletes all the streams that have been closed from the _requestedStreams list. private void CleanUpRequestedStreamsList() { if (_requestedStreams != null) { for (int i = _requestedStreams.Count-1; i >= 0; i--) { if (IsStreamClosed(_requestedStreams[i])) _requestedStreams.RemoveAt(i); } } } //Detect if the stream has been closed. //When a stream is closed the three flags - CanSeek, CanRead and CanWrite //return false. These properties do not throw ObjectDisposedException. //So we rely on the values of these properties to determine if a stream //has been closed. private bool IsStreamClosed(Stream s) { if (s.CanRead == false && s.CanSeek == false && s.CanWrite == false) return true; else return false; } #endregion Private Methods //----------------------------------------------------- // // Private Fields // //----------------------------------------------------- #region Private Members private PackUriHelper.ValidatedPartUri _uri; private Package _container; private ContentType _contentType; private List _requestedStreams; private InternalRelationshipCollection _relationships; private CompressionOption _compressionOption = CompressionOption.NotCompressed; private bool _disposed; private bool _deleted; private bool _isRelationshipPart; #endregion Private Members } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------------------------ // // // Copyright (C) Microsoft Corporation. All rights reserved. // // // Description: // This is a base abstract class for PackagePart. This is a part of the // Packaging Layer // // History: // 01/03/2004: SarjanaS: Initial creation. [Stubs Only] // 03/01/2004: SarjanaS: Implemented the functionality for all the members. // 03/17/2004: BruceMac: Initial implementation or PackageRelationship methods // //----------------------------------------------------------------------------- using System; using System.IO; using System.Collections; using System.Windows; // For Exception strings - SRID using System.Collections.Generic; // For List <> using MS.Internal.IO.Packaging; using System.Diagnostics; // For Debug.Assert using MS.Internal; // For Invariant.Assert #pragma warning disable 1634, 1691 // suppressing PreSharp warnings namespace System.IO.Packaging { ////// This class represents the a PackagePart within a container. /// This is a part of the Packaging Layer APIs /// public abstract class PackagePart { //----------------------------------------------------- // // Public Constructors // //----------------------------------------------------- #region Protected Constructor ////// Protected constructor for the abstract Base class. /// This is the current contract between the subclass and the base class /// If we decide some registration mechanism then this might change /// /// You should use this constructor in the rare case when you do not have /// the content type information related to this part and would prefer to /// obtain it later as required. /// /// These parts have the CompressionOption as NotCompressed by default. /// /// NOTE : If you are using this constructor from your subclass or passing a null /// for the content type parameter, be sure to implement the GetContentTypeCore /// method, as that will be called to get the content type value. This is provided /// to enable lazy initialization of the ContentType property. /// /// /// Package in which this part is being created /// uri of the part ///If parameter "package" is null ///If parameter "partUri" is null protected PackagePart(Package package, Uri partUri) :this(package, partUri, null, CompressionOption.NotCompressed) { } ////// Protected constructor for the abstract Base class. /// This is the current contract between the subclass and the base class /// If we decide some registration mechanism then this might change /// /// These parts have the CompressionOption as NotCompressed by default. /// /// NOTE : If you are using this constructor from your subclass or passing a null /// for the content type parameter, be sure to implement the GetContentTypeCore /// method, as that will be called to get the content type value. This is provided /// to enable lazy initialization of the ContentType property. /// /// /// Package in which this part is being created /// uri of the part /// Content Type of the part, can be null if the value /// is unknown at the time of construction. However the value has to be made /// available anytime the ContentType property is called. A null value only indicates /// that the value will be provided later. Every PackagePart must have a valid /// Content Type ///If parameter "package" is null ///If parameter "partUri" is null ///If parameter "partUri" does not conform to the valid partUri syntax protected PackagePart(Package package, Uri partUri, string contentType) :this(package, partUri, contentType, CompressionOption.NotCompressed) { } ////// Protected constructor for the abstract Base class. /// This is the current contract between the subclass and the base class /// If we decide some registration mechanism then this might change /// /// NOTE : If you are using this constructor from your subclass or passing a null /// for the content type parameter, be sure to implement the GetContentTypeCore /// method, as that will be called to get the content type value. This is provided /// to enable lazy initialization of the ContentType property. /// /// /// Package in which this part is being created /// uri of the part /// Content Type of the part, can be null if the value /// is unknown at the time of construction. However the value has to be made /// available anytime the ContentType property is called. A null value only indicates /// that the value will be provided later. Every PackagePart must have a valid /// Content Type /// compression option for this part ///If parameter "package" is null ///If parameter "partUri" is null ///If CompressionOption enumeration [compressionOption] does not have one of the valid values ///If parameter "partUri" does not conform to the valid partUri syntax protected PackagePart(Package package, Uri partUri, string contentType, CompressionOption compressionOption) { if (package == null) throw new ArgumentNullException("package"); if (partUri == null) throw new ArgumentNullException("partUri"); Package.ThrowIfCompressionOptionInvalid(compressionOption); _uri = PackUriHelper.ValidatePartUri(partUri); _container = package; if (contentType == null) _contentType = null; else _contentType = new ContentType(contentType); _requestedStreams = null; _compressionOption = compressionOption; _isRelationshipPart = PackUriHelper.IsRelationshipPartUri(partUri); } #endregion Protected Constructor //------------------------------------------------------ // // Public Properties // //----------------------------------------------------- #region Public Properties ////// The Uri for this PackagePart. It is always relative to the Package Root /// The PackagePart properties can not be accessed if the parent container is closed. /// ////// If this part has been deleted ///If the parent package has been closed or disposed public Uri Uri { get { CheckInvalidState(); return _uri; } } ////// The Content type of the stream that is represented by this part. /// The PackagePart properties can not be accessed if the parent container is closed. /// The content type value can be provided by the underlying physical format /// implementation at the time of creation of the Part object ( constructor ) or /// We can initialize it in a lazy manner when the ContentType property is called /// called for the first time by calling the GetContentTypeCore method. /// Note: This method GetContentTypeCore() is only for lazy initialization of the Content /// type value and will only be called once. There is no way to change the content type of /// the part once it has been assigned. /// ///Content Type of the Part [can never return null] ///If this part has been deleted ///If the parent package has been closed or disposed ///If the subclass fails to provide a non-null content type value. public string ContentType { get { CheckInvalidState(); if (_contentType == null) { //Lazy initialization for the content type string contentType = GetContentTypeCore(); if (contentType == null) { // From sarjanas: // // We have seen this bug in the past and have said that this should be // treated as exception. If we get a null content type, it’s an error. // We want to throw this exception so that anyone sub-classing this class // should not be setting the content type to null. Its like any other // parameter validation. This is the only place we can validate it. We // throw an ArgumentNullException, when the content type is set to null // in the constructor. // // We cannot get rid of this exception. At most, we can change it to // Invariant.Assert. But then client code will see an Assert if they make // a mistake and that is also not desirable. // // PackagePart is a public API. #pragma warning suppress 6503 throw new InvalidOperationException(SR.Get(SRID.NullContentTypeProvided)); } _contentType = new ContentType(contentType); } return _contentType.ToString(); } } ////// The parent container for this PackagePart /// The PackagePart properties can not be accessed if the parent container is closed. /// ////// If this part has been deleted ///If the parent package has been closed or disposed public Package Package { get { CheckInvalidState(); return _container; } } ////// CompressionOption class that was provided as a parameter during the original CreatePart call. /// The PackagePart properties can not be accessed if the parent container is closed. /// ///If this part has been deleted ///If the parent package has been closed or disposed public CompressionOption CompressionOption { get { CheckInvalidState(); return _compressionOption; } } #endregion Public Properties //------------------------------------------------------ // // Public Methods // //------------------------------------------------------ #region Public Methods #region Content Type Method ////// Custom Implementation for the GetContentType Method /// This method should only be implemented by those physical format implementors where /// the value for the content type cannot be provided at the time of construction of /// Part object and if calculating the content type value is a non-trivial or costly /// operation. The return value has to be a valid ContentType. This method will be used in /// real corner cases. The most common usage should be to provide the content type in the /// constructor. /// This method is only for lazy initialization of the Content type value and will only /// be called once. There is no way to change the content type of the part once it is /// assigned. /// ///Content type for the Part ///By default, this method throws a NotSupportedException. If a subclass wants to /// initialize the content type for a PackagePart in a lazy manner they must override this method. protected virtual string GetContentTypeCore() { throw new NotSupportedException(SR.Get(SRID.GetContentTypeCoreNotImplemented)); } #endregion Content Type Method #region Stream Methods ////// Returns the underlying stream that is represented by this part /// with the default FileMode and FileAccess /// Note: If you are requesting a stream for a relationship part and /// at the same time using relationship APIs to manipulate relationships, /// the final persisted data will depend on which data gets flushed last. /// ////// If this part has been deleted ///If the parent package has been closed or disposed ///If the subclass fails to provide a non-null stream object public Stream GetStream() { CheckInvalidState(); return GetStream(FileMode.OpenOrCreate, _container.FileOpenAccess); } ////// Returns the underlying stream in the specified mode and the /// default FileAccess /// Note: If you are requesting a stream for a relationship part for editing /// and at the same time using relationship APIs to manipulate relationships, /// the final persisted data will depend on which data gets flushed last. /// /// ////// If this part has been deleted ///If the parent package has been closed or disposed ///If FileMode enumeration [mode] does not have one of the valid values ///If FileAccess.Read is provided and FileMode values are any of the following - /// FileMode.Create, FileMode.CreateNew, FileMode.Truncate, FileMode.Append ///If the mode and access for the Package and the Stream are not compatible ///If the subclass fails to provide a non-null stream object public Stream GetStream(FileMode mode) { CheckInvalidState(); return GetStream(mode, _container.FileOpenAccess); } ////// Returns the underlying stream that is represented by this part /// in the specified mode with the access. /// Note: If you are requesting a stream for a relationship part and /// at the same time using relationship APIs to manipulate relationships, /// the final persisted data will depend on which data gets flushed last. /// /// /// ////// If this part has been deleted ///If the parent package has been closed or disposed ///If FileMode enumeration [mode] does not have one of the valid values ///If FileAccess enumeration [access] does not have one of the valid values ///If FileAccess.Read is provided and FileMode values are any of the following - /// FileMode.Create, FileMode.CreateNew, FileMode.Truncate, FileMode.Append ///If the mode and access for the Package and the Stream are not compatible ///If the subclass fails to provide a non-null stream object public Stream GetStream(FileMode mode, FileAccess access) { CheckInvalidState(); ThrowIfOpenAccessModesAreIncompatible(mode, access); Stream s = GetStreamCore(mode, access); if (s == null) throw new IOException(SR.Get(SRID.NullStreamReturned)); //Detect if any stream implementations are returning all three //properties - CanSeek, CanWrite and CanRead as false. Such a //stream should be pretty much useless. And as per current programming //practice, these properties are all false, when the stream has been //disposed. Debug.Assert(!IsStreamClosed(s)); //Lazy init if(_requestedStreams==null) _requestedStreams = new List(); //Default capacity is 4 //Delete all the closed streams from the _requestedStreams list. //Each time a new stream is handed out, we go through the list //to clean up streams that were handed out and have been closed. //Thus those stream can be garbage collected and we will avoid //keeping around stream objects that have been disposed CleanUpRequestedStreamsList(); _requestedStreams.Add(s); return s; } /// /// Custom Implementation for the GetSream Method /// /// /// ///protected abstract Stream GetStreamCore(FileMode mode, FileAccess access); #endregion Stream Methods #region PackageRelationship Methods /// /// Adds a relationship to this PackagePart with the Target PackagePart specified as the Uri /// Initial and trailing spaces in the name of the PackageRelationship are trimmed. /// /// /// Enumeration indicating the base uri for the target uri /// PackageRelationship type, having uri like syntax that is used to /// uniquely identify the role of the relationship ////// If this part has been deleted ///If the parent package has been closed or disposed ///If the package is readonly, it cannot be modified ///If parameter "targetUri" is null ///If parameter "relationshipType" is null ///If parameter "targetMode" enumeration does not have a valid value ///If TargetMode is TargetMode.Internal and the targetUri is an absolute Uri ///If relationship is being targeted to a relationship part public PackageRelationship CreateRelationship(Uri targetUri, TargetMode targetMode, string relationshipType) { return CreateRelationship(targetUri, targetMode, relationshipType, null); } ////// Adds a relationship to this PackagePart with the Target PackagePart specified as the Uri /// Initial and trailing spaces in the name of the PackageRelationship are trimmed. /// /// /// Enumeration indicating the base uri for the target uri /// PackageRelationship type, having uri like syntax that is used to /// uniquely identify the role of the relationship /// String that conforms to the xsd:ID datatype. Unique across the source's /// relationships. Null is OK (ID will be generated). An empty string is an invalid XML ID. ////// If this part has been deleted ///If the parent package has been closed or disposed ///If the package is readonly, it cannot be modified ///If parameter "targetUri" is null ///If parameter "relationshipType" is null ///If parameter "targetMode" enumeration does not have a valid value ///If TargetMode is TargetMode.Internal and the targetUri is an absolute Uri ///If relationship is being targeted to a relationship part ///If parameter "id" is not a valid Xsd Id ///If an id is provided in the method, and its not unique public PackageRelationship CreateRelationship(Uri targetUri, TargetMode targetMode, string relationshipType, String id) { CheckInvalidState(); _container.ThrowIfReadOnly(); EnsureRelationships(); //All parameter validation is done in the following method return _relationships.Add(targetUri, targetMode, relationshipType, id); } ////// Deletes a relationship from the PackagePart. This is done based on the /// relationship's ID. The target PackagePart is not affected by this operation. /// /// The ID of the relationship to delete. An invalid ID will not /// throw an exception, but nothing will be deleted. ///If this part has been deleted ///If the parent package has been closed or disposed ///If the package is readonly, it cannot be modified ///If parameter "id" is null ///If parameter "id" is not a valid Xsd Id public void DeleteRelationship(string id) { CheckInvalidState(); _container.ThrowIfReadOnly(); _container.ThrowIfInStreamingCreation("DeleteRelationship"); if (id == null) throw new ArgumentNullException("id"); InternalRelationshipCollection.ThrowIfInvalidXsdId(id); EnsureRelationships(); _relationships.Delete(id); } ////// Returns a collection of all the Relationships that are /// owned by this PackagePart /// ////// If this part has been deleted ///If the parent package has been closed or disposed ///If the package is write only, no information can be retrieved from it public PackageRelationshipCollection GetRelationships() { //All the validations for dispose and file access are done in the //GetRelationshipsHelper method. return GetRelationshipsHelper(null); } ////// Returns a collection of filtered Relationships that are /// owned by this PackagePart /// The relationshipType string is compared with the type of the relationships /// in a case sensitive and culture ignorant manner. /// ////// If this part has been deleted ///If the parent package has been closed or disposed ///If the package is write only, no information can be retrieved from it ///If parameter "relationshipType" is null ///If parameter "relationshipType" is an empty string public PackageRelationshipCollection GetRelationshipsByType(string relationshipType) { //These checks are made in the GetRelationshipsHelper as well, but we make them //here as we need to perform parameter validation CheckInvalidState(); _container.ThrowIfWriteOnly(); if (relationshipType == null) throw new ArgumentNullException("relationshipType"); InternalRelationshipCollection.ThrowIfInvalidRelationshipType(relationshipType); return GetRelationshipsHelper(relationshipType); } ////// Retrieve a relationship per ID. /// /// The relationship ID. ///The relationship with ID 'id' or throw an exception if not found. ///If this part has been deleted ///If the parent package has been closed or disposed ///If the package is write only, no information can be retrieved from it ///If parameter "id" is null ///If parameter "id" is not a valid Xsd Id ///If the requested relationship does not exist in the Package public PackageRelationship GetRelationship(string id) { //All the validations for dispose and file access are done in the //GetRelationshipHelper method. PackageRelationship returnedRelationship = GetRelationshipHelper(id); if (returnedRelationship == null) throw new InvalidOperationException(SR.Get(SRID.PackagePartRelationshipDoesNotExist)); else return returnedRelationship; } ////// Returns whether there is a relationship with the specified ID. /// /// The relationship ID. ///true iff a relationship with ID 'id' is defined on this source. ///If this part has been deleted ///If the parent package has been closed or disposed ///If the package is write only, no information can be retrieved from it ///If parameter "id" is null ///If parameter "id" is not a valid Xsd Id public bool RelationshipExists(string id) { //All the validations for dispose and file access are done in the //GetRelationshipHelper method. return (GetRelationshipHelper(id) != null); } #endregion PackageRelationship Methods #endregion Public Methods //----------------------------------------------------- // // Public Events // //------------------------------------------------------ // None //----------------------------------------------------- // // Internal Constructors // //----------------------------------------------------- // None //----------------------------------------------------- // // Internal Properties // //------------------------------------------------------ #region Internal Properties internal bool IsRelationshipPart { get { return _isRelationshipPart; } } //This property can be set to indicate if the part has been deleted internal bool IsDeleted { get { return _deleted; } set { _deleted = value; } } //This property can be set to indicate if the part has been deleted internal bool IsClosed { get { return _disposed; } } ////// This property returns the content type of the part /// as a validated strongly typed ContentType object /// internal ContentType ValidatedContentType { get { return _contentType; } } #endregion Internal Properties //----------------------------------------------------- // // Internal Methods // //------------------------------------------------------ #region Internal Methods //Delete all the relationships for this part internal void ClearRelationships() { if(_relationships!=null) _relationships.Clear(); } //Flush all the streams that are currently opened for this part and the relationships for this part //Note: This method is never be called on a deleted part internal void Flush() { Debug.Assert(_deleted != true, "PackagePart.Flush should never be called on a deleted part"); if (_requestedStreams!= null) { foreach (Stream s in _requestedStreams) { // Streams in this list are never set to null, so we do not need to check for // stream being null; However it could be closed by some external code. In that case // this property (CanWrite) will still be accessible and we can check to see // whether we can call flush or no. if (s.CanWrite) s.Flush(); } } // Relationships for this part should have been flushed earlier in the Package.Flush method. } //Close all the streams that are open for this part. internal void Close() { if (!_disposed) { try { if (_requestedStreams != null) { //Adding this extra check here to optimize delete operation //Everytime we delete a part we close it before deleting to //ensure that its deleted in a valid state. However, we do not //need to persist any changes if the part is being deleted. if (!_deleted) { foreach (Stream s in _requestedStreams) { s.Close(); } } _requestedStreams.Clear(); } // In streaming creation, if the part has had no stream opened on it, // it has not been physically added to the archive yet. else if (_container.InStreamingCreation) { // Create an interleaving stream to make sure a physical item gets created. GetStream(FileMode.CreateNew, _container.FileOpenAccess).Close(); } // Relationships for this part should have been flushed/closed earlier in the Package.Close method. } finally { _requestedStreams = null; //InternalRelationshipCollection is not required any more _relationships = null; //Once the container is closed there is no way to get to the stream or any other part //in the container. _container = null; //We do not need to explicitly call GC.SuppressFinalize(this) _disposed = true; } } } #region Write-Time Streaming API ////// According to the access mode (streaming or not), /// write the whole relationships part or just a nonterminal /// nonterminal piece for the relationships part. /// ////// The behavior of _relationships.Flush, which gets invoked here, will vary /// according as the package was opened for streaming production or not. /// internal void FlushRelationships() { Debug.Assert(_deleted != true, "PackagePart.FlushRelationsips should never be called on a deleted part"); // flush relationships if (_relationships != null && _container.FileOpenAccess != FileAccess.Read) { _relationships.Flush(); } } internal void CloseRelationships() { if (!_deleted) { //Flush the relationships for this part. if (_container.InStreamingCreation) { // Flush unsaved relationships, // close XML markup and save as the last piece. CloseStreamingRelationships(); } else { FlushRelationships(); } } } ////// Write a terminal piece for folderPath/_rels/baseName.rels /// private void CloseStreamingRelationships() { if (!_container.InStreamingCreation) throw new IOException(SR.Get(SRID.MethodAvailableOnlyInStreamingCreation, "CloseRelationships")); if (_relationships == null) return; // No relationship has been created. _relationships.CloseInStreamingCreationMode(); } #endregion Write-Time Streaming API #endregion Internal Methods //------------------------------------------------------ // // Internal Events // //----------------------------------------------------- // None //------------------------------------------------------ // // Private Methods // //----------------------------------------------------- #region Private Methods // lazy init private void EnsureRelationships() { if (_relationships == null) { // check here ThrowIfRelationship(); // obtain the relationships from the PackageRelationship part (if available) _relationships = new InternalRelationshipCollection(this); } } //Make sure that the access modes for the container and the part are compatible private void ThrowIfOpenAccessModesAreIncompatible(FileMode mode, FileAccess access) { Package.ThrowIfFileModeInvalid(mode); Package.ThrowIfFileAccessInvalid(access); //Creating a part using a readonly stream. if(access == FileAccess.Read && (mode == FileMode.Create || mode == FileMode.CreateNew || mode == FileMode.Truncate || mode == FileMode.Append)) throw new IOException(SR.Get(SRID.UnsupportedCombinationOfModeAccess)); //Incompatible access modes between container and part stream. if((_container.FileOpenAccess == FileAccess.Read && access != FileAccess.Read) || (_container.FileOpenAccess == FileAccess.Write && access != FileAccess.Write) ) throw new IOException(SR.Get(SRID.ContainerAndPartModeIncompatible)); } //Check if the part is in an invalid state private void CheckInvalidState() { ThrowIfPackagePartDeleted(); ThrowIfParentContainerClosed(); } //If the parent container is closed then the operations on this part like getting stream make no sense private void ThrowIfParentContainerClosed() { if (_container == null) throw new InvalidOperationException(SR.Get(SRID.ParentContainerClosed)); } //If the part has been deleted then we throw private void ThrowIfPackagePartDeleted() { if (_deleted == true) throw new InvalidOperationException(SR.Get(SRID.PackagePartDeleted)); } // some operations are invalid if we are a relationship part private void ThrowIfRelationship() { if (IsRelationshipPart) throw new InvalidOperationException(SR.Get(SRID.RelationshipPartsCannotHaveRelationships)); } ////// Retrieve a relationship per ID. /// /// The relationship ID. ///The relationship with ID 'id' or null if not found. private PackageRelationship GetRelationshipHelper(string id) { CheckInvalidState(); _container.ThrowIfWriteOnly(); if (id == null) throw new ArgumentNullException("id"); InternalRelationshipCollection.ThrowIfInvalidXsdId(id); EnsureRelationships(); return _relationships.GetRelationship(id); } ////// Returns a collection of all the Relationships that are /// owned by this PackagePart, based on the filter string /// ///private PackageRelationshipCollection GetRelationshipsHelper(string filterString) { CheckInvalidState(); _container.ThrowIfWriteOnly(); EnsureRelationships(); //Internally null is used to indicate that no filter string was specified and //and all the relationships should be returned. return new PackageRelationshipCollection(_relationships, filterString); } //Deletes all the streams that have been closed from the _requestedStreams list. private void CleanUpRequestedStreamsList() { if (_requestedStreams != null) { for (int i = _requestedStreams.Count-1; i >= 0; i--) { if (IsStreamClosed(_requestedStreams[i])) _requestedStreams.RemoveAt(i); } } } //Detect if the stream has been closed. //When a stream is closed the three flags - CanSeek, CanRead and CanWrite //return false. These properties do not throw ObjectDisposedException. //So we rely on the values of these properties to determine if a stream //has been closed. private bool IsStreamClosed(Stream s) { if (s.CanRead == false && s.CanSeek == false && s.CanWrite == false) return true; else return false; } #endregion Private Methods //----------------------------------------------------- // // Private Fields // //----------------------------------------------------- #region Private Members private PackUriHelper.ValidatedPartUri _uri; private Package _container; private ContentType _contentType; private List _requestedStreams; private InternalRelationshipCollection _relationships; private CompressionOption _compressionOption = CompressionOption.NotCompressed; private bool _disposed; private bool _deleted; private bool _isRelationshipPart; #endregion Private Members } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- KeyConstraint.cs
- Font.cs
- WindowsTreeView.cs
- SchemaImporterExtensionsSection.cs
- CollectionsUtil.cs
- FileRecordSequenceHelper.cs
- EmptyElement.cs
- Form.cs
- CompositeScriptReference.cs
- ListViewDeleteEventArgs.cs
- StringToken.cs
- Column.cs
- TextDecorationCollection.cs
- ProxyWebPartManager.cs
- GlyphRun.cs
- MetadataItemCollectionFactory.cs
- ConnectionStringsExpressionBuilder.cs
- NumericExpr.cs
- Membership.cs
- StorageBasedPackageProperties.cs
- QuadraticBezierSegment.cs
- IIS7WorkerRequest.cs
- SafeBuffer.cs
- ValidationHelper.cs
- StylusPointPropertyInfoDefaults.cs
- SQLDecimal.cs
- UmAlQuraCalendar.cs
- _ScatterGatherBuffers.cs
- Vector3DAnimationBase.cs
- SelectionListComponentEditor.cs
- BaseDataBoundControl.cs
- BuildDependencySet.cs
- VisualCollection.cs
- httpstaticobjectscollection.cs
- baseshape.cs
- SurrogateSelector.cs
- GeneralTransform3DGroup.cs
- DiagnosticsConfigurationHandler.cs
- GcHandle.cs
- RecognizedWordUnit.cs
- Aes.cs
- DataGridClipboardHelper.cs
- CacheAxisQuery.cs
- MenuBase.cs
- TypedElement.cs
- NeutralResourcesLanguageAttribute.cs
- AutoCompleteStringCollection.cs
- X509ChainPolicy.cs
- _KerberosClient.cs
- DocumentSchemaValidator.cs
- SafeBitVector32.cs
- ItemCollectionEditor.cs
- ToolboxItemCollection.cs
- TabletDeviceInfo.cs
- RSAPKCS1KeyExchangeFormatter.cs
- Bind.cs
- TreeNodeCollection.cs
- PolyLineSegment.cs
- BrowserTree.cs
- GridToolTip.cs
- BulletedListEventArgs.cs
- ConfigXmlCDataSection.cs
- ParseNumbers.cs
- RoutingSection.cs
- GlyphShapingProperties.cs
- BitVector32.cs
- SoapReflectionImporter.cs
- CellTreeNode.cs
- ListView.cs
- MediaPlayerState.cs
- DataGridClipboardCellContent.cs
- BooleanKeyFrameCollection.cs
- filewebresponse.cs
- AppDomainResourcePerfCounters.cs
- EntitySqlQueryState.cs
- PackWebRequest.cs
- DataContractSet.cs
- listitem.cs
- StructuredProperty.cs
- PatternMatcher.cs
- Vector3DIndependentAnimationStorage.cs
- ButtonBaseAutomationPeer.cs
- validationstate.cs
- CheckPair.cs
- OdbcConnectionString.cs
- DecoratedNameAttribute.cs
- FixedSOMElement.cs
- PrintPreviewDialog.cs
- WebHttpSecurity.cs
- XmlDocumentType.cs
- DataSetFieldSchema.cs
- ToolStripDropDownItem.cs
- GestureRecognitionResult.cs
- smtppermission.cs
- PhysicalOps.cs
- ItemCollection.cs
- MeasureItemEvent.cs
- ScopelessEnumAttribute.cs
- ProcessThread.cs
- DBNull.cs