Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Framework / System / Windows / Markup / BamlRecords.cs / 2 / BamlRecords.cs
/****************************************************************************\ * * File: BamlRecords.cs * * Purpose: Contains implementation for specific BamlRecords * * History: * 6/06/01: rogerg Created * 5/28/03: peterost Ported to wcp * 10/6/03: peterost Reorganized to remove DP - clr distinction * * Copyright (C) 2002 by Microsoft Corporation. All rights reserved. * \***************************************************************************/ using System; using System.Xml; using System.IO; using System.Text; using System.Collections.Generic; using System.Collections; using System.Globalization; using System.ComponentModel; using System.Security.Permissions; using System.Diagnostics; using System.Reflection; using System.Collections.Specialized; using MS.Internal.IO.Packaging.CompoundFile; #if PBTCOMPILER using TCH = MS.Internal.Markup.TypeConverterHelper; #else using System.Windows; using System.Windows.Media; using System.Windows.Threading; using MS.Internal.PresentationFramework; // SafeSecurityHelper using TCH = System.Windows.Markup.TypeConverterHelper; #endif using System.Runtime.InteropServices; using MS.Utility; using MS.Internal; // Disabling 1634 and 1691: // In order to avoid generating warnings about unknown message numbers and // unknown pragmas when compiling C# source code with the C# compiler, // you need to disable warnings 1634 and 1691. (Presharp Documentation) #pragma warning disable 1634, 1691 #if PBTCOMPILER namespace MS.Internal.Markup #else namespace System.Windows.Markup #endif { // Types of records. Note that this is a superset of XamlNodeTypes internal enum BamlRecordType : byte { ////// Unknown Node /// // !!BamlRecordManager class relies on Unknown = 0 for initialization Unknown = 0, ////// Start Document Node /// DocumentStart, // 1 ////// End Document Node /// DocumentEnd, // 2 ////// Start Element Node, which may be a CLR object or a DependencyObject /// ElementStart, // 3 ////// End Element Node /// ElementEnd, // 4 ////// Property Node, which may be a CLR property or a DependencyProperty /// Property, // 5 ////// Binary serialization of a property /// PropertyCustom, // 6 ////// Complex Property Node /// PropertyComplexStart, // 7 ////// End Complex Property Node /// PropertyComplexEnd, // 8 ////// Start Array Property Node /// PropertyArrayStart, // 9 ////// End Array Property Node /// PropertyArrayEnd, // 10 ////// Star IList Property Node /// PropertyIListStart, // 11 ////// End PropertyIListStart Node /// PropertyIListEnd, // 12 ////// Start IDictionary Property Node /// PropertyIDictionaryStart, // 13 ////// End IDictionary Property Node /// PropertyIDictionaryEnd, // 14 ////// LiteralContent Node /// LiteralContent, // 15 ////// Text Node /// Text, // 16 ////// Text that has an associated custom typeconverter /// TextWithConverter, // 17 ////// RoutedEventNode /// RoutedEvent, // 18 ////// ClrEvent Node /// ClrEvent, // 19 ////// XmlnsProperty Node /// XmlnsProperty, // 20 ////// XmlAttribute Node /// XmlAttribute, // 21 ////// Processing Intstruction Node /// ProcessingInstruction, // 22 ////// Comment Node /// Comment, // 23 ////// DefTag Node /// DefTag, // 24 ////// x:name="value" attribute. One typical use of this /// attribute is to define a key to use when inserting an item into an IDictionary /// DefAttribute, // 25 ////// EndAttributes Node /// EndAttributes, // 26 ////// PI xml - clr namespace mapping /// PIMapping, // 27 ////// Assembly information /// AssemblyInfo, // 28 ////// Type information /// TypeInfo, // 29 ////// Type information for a Type that has an associated custom serializer /// TypeSerializerInfo, // 30 ////// Attribute (eg - properties and events) information /// AttributeInfo, // 31 ////// Resource information /// StringInfo, // 32 ////// Property Resource Reference /// PropertyStringReference, // 33 ////// Record for setting a property to a Type reference. This is used for /// properties that are of type "Type" /// PropertyTypeReference, // 34 ////// Property that has a simple MarkupExtension value. /// PropertyWithExtension, // 35 ////// Property that has an associated custom typeconverter /// PropertyWithConverter, // 36 ////// Start a deferable content block /// DeferableContentStart, // 37 ////// x:name="value" attribute when used within a defer load /// dictionary. These keys are hoisted to the front of the dictionary when /// written to baml. /// DefAttributeKeyString, // 38 ////// Implied key that is a Type attribute when used within a defer load /// dictionary. These keys are hoisted to the front of the dictionary when /// written to baml. /// DefAttributeKeyType, // 39 ////// This marks the start of an element tree that is used as the key in /// an IDictionary. /// KeyElementStart, // 40 ////// This marks the end of an element tree that is used as the key in /// an IDictionary. /// KeyElementEnd, // 41 ////// Record marks the start of a section containing constructor parameters /// ConstructorParametersStart, // 42 ////// Record marks the end of a section containing constructor parameters /// ConstructorParametersEnd, // 43 ////// Constructor parameter that has been resolved to a Type. /// ConstructorParameterType, // 44 ////// Record that has info about which event or id to connect to in an object tree. /// ConnectionId, // 45 ////// Record that set the conntent property context for the element /// ContentProperty, // 46 ////// ElementStartRecord that also carries an element name. /// NamedElementStart, // 47 ////// Start of StaticResourceExtension within the header of a deferred section. /// StaticResourceStart, // 48 ////// End of a StaticResourceExtension within the header of a deferred section. /// StaticResourceEnd, // 49 ////// BamlRecord that carries an identifier for a StaticResourceExtension /// within the header of a deferred section. /// StaticResourceId, // 50 ////// This is a TextRecord that holds an Id for the String value it represents. /// TextWithId, // 51 ////// PresentationOptions:Freeze="value" attribute. Used for ignorable /// WPF-specific parsing options /// PresentationOptionsAttribute, // 52 ////// Debugging information record that holds the source XAML linenumber. /// LineNumberAndPosition, // 53 ////// Debugging information record that holds the source XAML line position. /// LinePosition, // 54 ////// OptimizedStaticResourceExtension within the header of a deferred section. /// OptimizedStaticResource, // 55 ////// BamlPropertyRecord that carries an identifier for a StaticResourceExtension /// within the header of a deferred section. /// PropertyWithStaticResourceId, // 56 ////// Placeholder to mark last record /// LastRecordType } ////// Some attributes have special usages or cause additional actions when they /// are set on an element. This can be have some other effects /// such as setting the xml:lang or xml:space values in the parser context. /// The PropertyUsage describes addition effects or usage for this property. /// internal enum BamlAttributeUsage : short { ///A regular property that has no other use Default = 0, ///A property that has xml:lang information XmlLang, ///A property that has xml:space information XmlSpace, ///A property that has the RuntimeIdProperty information RuntimeName, } // This class handles allocation, read and write management of baml records. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlRecordManager { #if !PBTCOMPILER // Genericaly load and create the proper class. // This method assumes the seek pointer has already moved passed the recordType // field and is at the RecordSize or record contents (depending on record). // This method is used so the caller can first read the type of record, and expects // to get back the entire record, or nothing (for async support). internal BamlRecord ReadNextRecord( BinaryReader bamlBinaryReader, long bytesAvailable, BamlRecordType recordType) { BamlRecord bamlRecord; // = null // Create the proper BamlRecord based on the recordType. The assembly, // type and attribute records are created every time, since they are // used by the BamlMapTable. The other records are re-used, so they // are created once and cached. switch(recordType) { case BamlRecordType.AssemblyInfo: bamlRecord = new BamlAssemblyInfoRecord(); break; case BamlRecordType.TypeInfo: bamlRecord = new BamlTypeInfoRecord(); break; case BamlRecordType.TypeSerializerInfo: bamlRecord = new BamlTypeInfoWithSerializerRecord(); break; case BamlRecordType.AttributeInfo: bamlRecord = new BamlAttributeInfoRecord(); break; case BamlRecordType.StringInfo: bamlRecord = new BamlStringInfoRecord(); break; case BamlRecordType.DefAttributeKeyString: bamlRecord = new BamlDefAttributeKeyStringRecord(); break; case BamlRecordType.DefAttributeKeyType: bamlRecord = new BamlDefAttributeKeyTypeRecord(); break; case BamlRecordType.KeyElementStart: bamlRecord = new BamlKeyElementStartRecord(); break; default: // Get the current record from the cache. If there's nothing there yet, // or if what is there is pinned, then create one. Note that records in the // read cache are implicitly recycled, and records in the write cache are explicitly // recycled (i.e., there's a ReleaseWriteRecord, but no ReleaseReadRecord). bamlRecord = _readCache[(int)recordType]; if (null == bamlRecord || bamlRecord.IsPinned ) { bamlRecord = _readCache[(int)recordType] = AllocateRecord(recordType); } break; } bamlRecord.Next = null; if (null != bamlRecord) { // If LoadRecordSize indicates it can determine the record size // and has determined that there is enough content to load the // entire record, then continue. if (bamlRecord.LoadRecordSize(bamlBinaryReader, bytesAvailable) && bytesAvailable >= bamlRecord.RecordSize) { bamlRecord.LoadRecordData(bamlBinaryReader); } else { bamlRecord = null; } } return bamlRecord; } ////// Return the object if it should be treated as IAddChild, otherwise return null /// static internal IAddChild AsIAddChild(object obj) { IAddChild iac = obj as IAddChildInternal; return iac; } #endif ////// True if type should be treated as IAddChild /// static internal bool TreatAsIAddChild(Type parentObjectType) { return (KnownTypes.Types[(int)KnownElements.IAddChildInternal].IsAssignableFrom( parentObjectType )); } static internal BamlRecordType GetPropertyStartRecordType(Type propertyType, bool propertyCanWrite) { BamlRecordType recordType; if (propertyType.IsArray) { recordType = BamlRecordType.PropertyArrayStart; } else if (typeof(IDictionary).IsAssignableFrom(propertyType)) { recordType = BamlRecordType.PropertyIDictionaryStart; } else if ((typeof(IList).IsAssignableFrom(propertyType) || BamlRecordManager.TreatAsIAddChild(propertyType) || (typeof(IEnumerable).IsAssignableFrom(propertyType) && !propertyCanWrite))) { // we're a list if: // 1) the property type is an IList. // 2) the property type is an IAddChild (internal). // 3) the property type is an IEnumerable and read-only and the parent is an IAddChild (internal). // for the third case, we can't check the parent until run-time. recordType = BamlRecordType.PropertyIListStart; } else { recordType = BamlRecordType.PropertyComplexStart; } return recordType; } #if !PBTCOMPILER internal BamlRecord CloneRecord(BamlRecord record) { BamlRecord newRecord; switch (record.RecordType) { case BamlRecordType.ElementStart: if (record is BamlNamedElementStartRecord) { newRecord= new BamlNamedElementStartRecord(); } else { newRecord = new BamlElementStartRecord(); } break; case BamlRecordType.PropertyCustom: if (record is BamlPropertyCustomWriteInfoRecord) { newRecord = new BamlPropertyCustomWriteInfoRecord(); } else { newRecord = new BamlPropertyCustomRecord(); } break; default: newRecord = AllocateRecord(record.RecordType); break; } record.Copy(newRecord); return newRecord; } #endif // Helper function to create a BamlRecord from a BamlRecordType private BamlRecord AllocateWriteRecord(BamlRecordType recordType) { BamlRecord record; switch (recordType) { case BamlRecordType.PropertyCustom: record = new BamlPropertyCustomWriteInfoRecord(); break; default: record = AllocateRecord(recordType); break; } return record; } // Helper function to create a BamlRecord from a BamlRecordType private BamlRecord AllocateRecord(BamlRecordType recordType) { BamlRecord record; switch(recordType) { case BamlRecordType.DocumentStart: record = new BamlDocumentStartRecord(); break; case BamlRecordType.DocumentEnd: record = new BamlDocumentEndRecord(); break; case BamlRecordType.ConnectionId: record = new BamlConnectionIdRecord(); break; case BamlRecordType.ElementStart: record = new BamlElementStartRecord(); break; case BamlRecordType.ElementEnd: record = new BamlElementEndRecord(); break; case BamlRecordType.DeferableContentStart: record = new BamlDeferableContentStartRecord(); break; case BamlRecordType.DefAttributeKeyString: record = new BamlDefAttributeKeyStringRecord(); break; case BamlRecordType.DefAttributeKeyType: record = new BamlDefAttributeKeyTypeRecord(); break; case BamlRecordType.LiteralContent: record = new BamlLiteralContentRecord(); break; case BamlRecordType.Property: record = new BamlPropertyRecord(); break; case BamlRecordType.PropertyWithConverter: record = new BamlPropertyWithConverterRecord(); break; case BamlRecordType.PropertyStringReference: record = new BamlPropertyStringReferenceRecord(); break; case BamlRecordType.PropertyTypeReference: record = new BamlPropertyTypeReferenceRecord(); break; case BamlRecordType.PropertyWithExtension: record = new BamlPropertyWithExtensionRecord(); break; case BamlRecordType.PropertyCustom: record = new BamlPropertyCustomRecord(); break; case BamlRecordType.PropertyComplexStart: record = new BamlPropertyComplexStartRecord(); break; case BamlRecordType.PropertyComplexEnd: record = new BamlPropertyComplexEndRecord(); break; case BamlRecordType.RoutedEvent: record = new BamlRoutedEventRecord(); break; case BamlRecordType.PropertyArrayStart: record = new BamlPropertyArrayStartRecord(); break; case BamlRecordType.PropertyArrayEnd: record = new BamlPropertyArrayEndRecord(); break; case BamlRecordType.PropertyIListStart: record = new BamlPropertyIListStartRecord(); break; case BamlRecordType.PropertyIListEnd: record = new BamlPropertyIListEndRecord(); break; case BamlRecordType.PropertyIDictionaryStart: record = new BamlPropertyIDictionaryStartRecord(); break; case BamlRecordType.PropertyIDictionaryEnd: record = new BamlPropertyIDictionaryEndRecord(); break; case BamlRecordType.Text: record = new BamlTextRecord(); break; case BamlRecordType.TextWithConverter: record = new BamlTextWithConverterRecord(); break; case BamlRecordType.TextWithId: record = new BamlTextWithIdRecord(); break; case BamlRecordType.XmlnsProperty: record = new BamlXmlnsPropertyRecord(); break; case BamlRecordType.PIMapping: record = new BamlPIMappingRecord(); break; case BamlRecordType.DefAttribute: record = new BamlDefAttributeRecord(); break; case BamlRecordType.PresentationOptionsAttribute: record = new BamlPresentationOptionsAttributeRecord(); break; case BamlRecordType.KeyElementStart: record = new BamlKeyElementStartRecord(); break; case BamlRecordType.KeyElementEnd: record = new BamlKeyElementEndRecord(); break; case BamlRecordType.ConstructorParametersStart: record = new BamlConstructorParametersStartRecord(); break; case BamlRecordType.ConstructorParametersEnd: record = new BamlConstructorParametersEndRecord(); break; case BamlRecordType.ConstructorParameterType: record = new BamlConstructorParameterTypeRecord(); break; case BamlRecordType.ContentProperty: record = new BamlContentPropertyRecord(); break; case BamlRecordType.AssemblyInfo: case BamlRecordType.TypeInfo: case BamlRecordType.TypeSerializerInfo: case BamlRecordType.AttributeInfo: case BamlRecordType.StringInfo: Debug.Assert(false,"Assembly, Type and Attribute records are not cached, so don't ask for one."); record = null; break; case BamlRecordType.StaticResourceStart: record = new BamlStaticResourceStartRecord(); break; case BamlRecordType.StaticResourceEnd: record = new BamlStaticResourceEndRecord(); break; case BamlRecordType.StaticResourceId: record = new BamlStaticResourceIdRecord(); break; case BamlRecordType.LineNumberAndPosition: record = new BamlLineAndPositionRecord(); break; case BamlRecordType.LinePosition: record = new BamlLinePositionRecord(); break; case BamlRecordType.OptimizedStaticResource: record = new BamlOptimizedStaticResourceRecord(); break; case BamlRecordType.PropertyWithStaticResourceId: record = new BamlPropertyWithStaticResourceIdRecord(); break; default: Debug.Assert(false,"Unknown RecordType"); record = null; break; } return record; } // This should only be called from BamlRecordWriter -- it gets a record from the record // cache that must be freed with ReleaseRecord before GetRecord is called again. internal BamlRecord GetWriteRecord(BamlRecordType recordType) { // Create the cache of records used in writing, on demand if( _writeCache == null ) { _writeCache = new BamlRecord[(int)BamlRecordType.LastRecordType]; } BamlRecord record = _writeCache[(int)recordType]; if (null == record) { record = AllocateWriteRecord(recordType); } else { _writeCache[(int)recordType] = null; } // It is important to set RecordSize for variable size records // to a negative number to indicate that it has not been set yet. // Fixed size records should ignore this set. record.RecordSize = -1; return record; } //+--------------------------------------------------------------------------------------------- // // ReleaseWriteRecord // // Frees a record originally claimed with GetWriteRecord. Note that records in the // read cache are implicitly recycled, and records in the write cache are explicitly // recycled (i.e., there's a ReleaseWriteRecord, but no ReleaseReadRecord). // //+--------------------------------------------------------------------------------------------- internal void ReleaseWriteRecord(BamlRecord record) { // Put the write record back into the cache, if we're allowed to recycle it. if( !record.IsPinned ) { Debug.Assert(null == _writeCache[(int)record.RecordType]); if (null != _writeCache[(int)record.RecordType]) { // This is really an internal error. throw new InvalidOperationException(SR.Get(SRID.ParserMultiBamls)); } _writeCache[(int)record.RecordType] = record; } } // Cache of BamlRecords, used during read, to avoid lots of records from being // created. If a record gets pinned (BamlRecord.IsPinned gets set), it is not re-used. #if !PBTCOMPILER BamlRecord[] _readCache = new BamlRecord[(int)BamlRecordType.LastRecordType]; #endif // Cache of BamlRecords, used during write, also to avoid lots of records // from being created. BamlRecord[] _writeCache = null; //new BamlRecord[(int)BamlRecordType.LastRecordType]; } // The base of all baml records. This gives a fixed size record that contains // line number information used for generating error messages. Note that the // line number information is not currently written out to the baml stream. internal abstract class BamlRecord { #region Methods #if !PBTCOMPILER // If there are enough bytes available, load the record size from the // binary reader. For fixed size records that derive from BamlRecord, // there is no size field in the baml file, so this always succeeds. internal virtual bool LoadRecordSize( BinaryReader bamlBinaryReader, long bytesAvailable) { return true; } // Load record data. This does not include the record type, or the // size field, which are loaded separately. If the subclass has no // specific data to load, then don't override this. internal virtual void LoadRecordData(BinaryReader bamlBinaryReader) { } #endif // Writes data at the current position seek pointer points // to byte after the end of record when done. internal virtual void Write(BinaryWriter bamlBinaryWriter) { // BamlRecords may be used without a stream, so if you attempt to write when there // isn't a writer, just ignore it. if (bamlBinaryWriter == null) { return; } // Baml records always start with record type bamlBinaryWriter.Write((byte) RecordType); // IMPORTANT: The RecordType is the last thing written before calling // WriteRecordData. Some records assume the record type is located // directly before the current stream location and may change it, so // don't change where the record type is written in the stream!!! // Paint is one example of a DP object that will seek back to change // the record type if it is unable to serialize itself. WriteRecordData(bamlBinaryWriter); } // Write contents of the record, excluding size (if any) and record type. // If the subclass has no specific data to write out, don't override this. internal virtual void WriteRecordData(BinaryWriter bamlBinaryWriter) { } #endregion Methods #region Properties // Actual size of the complete BamlRecord (excluding RecordType) in bytes. // Currently limited to 2 gigabytes. Default size is 0 bytes of data. // Subclasses must override if they have a different size. internal virtual Int32 RecordSize { get { return 0; } set { Debug.Assert (value == -1, "Setting fixed record to an invalid size"); } } // Identifies the type off BAML record. This is used when casting to // a BamlRecord subclass. All subclasses **MUST** override this. internal virtual BamlRecordType RecordType { get { Debug.Assert(false, "Must override RecordType"); return BamlRecordType.Unknown; } } #if !PBTCOMPILER // Next Record pointer - used in BamlObjectFactory internal BamlRecord Next { get { return _nextRecord; } set { _nextRecord = value ; } } #endif // The BamlRecorManager keeps a cache of baml records and tries to reuse them automatically. // To keep a record from being cached, it can be pinned. For correct pinning we keep a // pin count. To save working set, we only have two bits for the reference count. // So if the reference count reaches three the record becomes permanently pinned. internal bool IsPinned { get { return PinnedCount > 0; } } // (See comment on IsPinned.) internal int PinnedCount { get { return _flags[_pinnedFlagSection]; } set { Debug.Assert( value <= 3 && value >= 0 ); _flags[_pinnedFlagSection] = value; } } // (See comment on IsPinned.) internal void Pin() { if( PinnedCount < 3 ) { ++PinnedCount; } } #if !PBTCOMPILER // (See comment on IsPinned.) internal void Unpin() { if( PinnedCount < 3 ) { --PinnedCount; } } internal virtual void Copy(BamlRecord record) { record._flags = _flags; record._nextRecord = _nextRecord; } #endif #endregion Properties #region Data // Internal flags for efficient storage // NOTE: bits here are used by sub-classes also. // This BitVector32 field is shared by subclasses to save working set. Sharing flags like this // is easier in e.g. FrameworkElement, where the class hierarchy is linear, but can be bug-prone otherwise. To make the // code less fragile, each class abstractly provides it's last section to subclasses(LastFlagsSection), which they can // use in their call to CreateSection. internal BitVector32 _flags; // Allocate space in _flags. private static BitVector32.Section _pinnedFlagSection = BitVector32.CreateSection( 3 /* Allocates two bits to store values up to 3 */ ); // This provides subclasses with a referece section to create their own section. internal static BitVector32.Section LastFlagsSection { get { return _pinnedFlagSection; } } #if !PBTCOMPILER private BamlRecord _nextRecord = null; #endif // Size of the record type field in the baml file. internal const int RecordTypeFieldLength = 1; #if !PBTCOMPILER public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0}", RecordType); } protected static string GetTypeName(int typeId) { string typeName = typeId.ToString(CultureInfo.InvariantCulture); if(typeId < 0) { KnownElements elm = (KnownElements)(-typeId); typeName = elm.ToString(); } return typeName; } // This helper checks for records that indicate that you're out of // an element start, and into it's "content" (in the xml sense). // We have to infer this, because unlike Xml, Baml doesn't provide // an end-attributes record. internal static bool IsContentRecord( BamlRecordType bamlRecordType ) { return bamlRecordType == BamlRecordType.PropertyComplexStart || bamlRecordType == BamlRecordType.PropertyArrayStart || bamlRecordType == BamlRecordType.PropertyIListStart || bamlRecordType == BamlRecordType.PropertyIDictionaryStart || bamlRecordType == BamlRecordType.Text; } #endif #endregion Data } // An abstract base class for records that record their size as part of the // baml stream. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal abstract class BamlVariableSizedRecord : BamlRecord { #region Methods #if !PBTCOMPILER // If there are enough bytes available, load the record size from the // binary reader. The default action is to load the 4 byte size from // the reader, if there are at least 4 bytes available. internal override bool LoadRecordSize( BinaryReader bamlBinaryReader, long bytesAvailable) { int recordSize; bool loadedSize = LoadVariableRecordSize(bamlBinaryReader, bytesAvailable, out recordSize); if (loadedSize) { RecordSize = recordSize; } return loadedSize; } // If there are enough bytes available, load the record size from the // binary reader. The default action is to load the 4 byte size from // the reader, if there are at least 4 bytes available. internal static bool LoadVariableRecordSize( BinaryReader bamlBinaryReader, long bytesAvailable, out int recordSize) { if (bytesAvailable >= MaxRecordSizeFieldLength) { recordSize = ((BamlBinaryReader)bamlBinaryReader).Read7BitEncodedInt(); return true; } else { recordSize = -1; return false; } } #endif protected int ComputeSizeOfVariableLengthRecord(long start, long end) { int size = (Int32)(end - start); int sizeOfSize = BamlBinaryWriter.SizeOf7bitEncodedSize(size); sizeOfSize = BamlBinaryWriter.SizeOf7bitEncodedSize(sizeOfSize+size); return (sizeOfSize+size); } // Writes data at the current position seek pointer points // to byte after the end of record when done. internal override void Write(BinaryWriter bamlBinaryWriter) { // BamlRecords may be used without a stream, so if you attempt to write when there // isn't a writer, just ignore it. if (bamlBinaryWriter == null) { return; } // Baml records always start with record type bamlBinaryWriter.Write((byte) RecordType); // Remember the file location of this baml record. This // is needed if we have to come back later to update the [....] mode. // IMPORTANT: The RecordType is the last thing written before calling // WriteRecordData. Some records assume the record type is located // directly before the current stream location and may change it, so // don't change where the record type is written in the stream!!! // Paint is one example of a DP object that will seek back to change // the record type if it is unable to serialize itself. // Write just the data, this is just to measure the size. long startSeekPosition = bamlBinaryWriter.Seek(0,SeekOrigin.Current); WriteRecordData(bamlBinaryWriter); long endSeekPosition = bamlBinaryWriter.Seek(0,SeekOrigin.Current); Debug.Assert(RecordSize < 0); RecordSize = ComputeSizeOfVariableLengthRecord(startSeekPosition, endSeekPosition); // seek back to the begining, this time write the size, then the data. bamlBinaryWriter.Seek((int)startSeekPosition, SeekOrigin.Begin); WriteRecordSize(bamlBinaryWriter); WriteRecordData(bamlBinaryWriter); } // Write the size of this record. The default action is to write the 4 byte // size, which may be overwritten later once WriteRecordData has been called. internal void WriteRecordSize(BinaryWriter bamlBinaryWriter) { ((BamlBinaryWriter)bamlBinaryWriter).Write7BitEncodedInt(RecordSize); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlVariableSizedRecord newRecord = (BamlVariableSizedRecord)record; newRecord._recordSize = _recordSize; } #endif #endregion Methods #region Properties // Actual size of the complete BamlRecord in bytes. Currently // limited to 2 gigabytes. internal override Int32 RecordSize { get { return _recordSize; } set { _recordSize = value; } } // This provides subclasses with a referece section to create their own section. internal new static BitVector32.Section LastFlagsSection { get { return BamlRecord.LastFlagsSection; } } #endregion Properties #region Data // Size of the RecordSize field in the baml file. This must be in // [....] the type type of _recordSize below. internal const int MaxRecordSizeFieldLength = 4; Int32 _recordSize = -1; // we use a 7 bit encoded variable size #endregion Data } //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlXmlnsPropertyRecord : BamlVariableSizedRecord { #region Methods #if !PBTCOMPILER // LoadRecord specific data internal override void LoadRecordData(BinaryReader bamlBinaryReader) { Prefix = bamlBinaryReader.ReadString(); XmlNamespace = bamlBinaryReader.ReadString(); short count = bamlBinaryReader.ReadInt16(); if (count > 0) { AssemblyIds = new short[count]; for (short i = 0; i < count; i++) { AssemblyIds[i] = bamlBinaryReader.ReadInt16(); } } else { AssemblyIds = null; } } #endif // write record specific Data. internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(Prefix); bamlBinaryWriter.Write(XmlNamespace); // Write the AssemblyIds which contain XmlnsDefinitionAttribute // for this xmlns Uri. // The format should be CountN Id1 Id2 ... IdN // short count = 0; if (AssemblyIds != null && AssemblyIds.Length > 0) { count = (short) AssemblyIds.Length; } bamlBinaryWriter.Write(count); if (count > 0) { for (short i = 0; i < count; i++) { bamlBinaryWriter.Write(AssemblyIds[i]); } } } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlXmlnsPropertyRecord newRecord = (BamlXmlnsPropertyRecord)record; newRecord._prefix = _prefix; newRecord._xmlNamespace = _xmlNamespace; newRecord._assemblyIds = _assemblyIds; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.XmlnsProperty; } } internal string Prefix { get { return _prefix; } set {_prefix = value; } } internal string XmlNamespace { get { return _xmlNamespace; } set { _xmlNamespace = value; } } internal short[] AssemblyIds { get { return _assemblyIds; } set { _assemblyIds = value; } } #endregion Properties #region Data string _prefix; string _xmlNamespace; short[] _assemblyIds; #endregion Data } //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPIMappingRecord : BamlVariableSizedRecord { #region Methods #if !PBTCOMPILER // LoadRecord specific data internal override void LoadRecordData(BinaryReader bamlBinaryReader) { XmlNamespace = bamlBinaryReader.ReadString(); ClrNamespace = bamlBinaryReader.ReadString(); AssemblyId = bamlBinaryReader.ReadInt16(); } #endif // write record specific Data. internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { // write out an int for record size but we'll go back and fill bamlBinaryWriter.Write(XmlNamespace); bamlBinaryWriter.Write(ClrNamespace); bamlBinaryWriter.Write(AssemblyId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlPIMappingRecord newRecord = (BamlPIMappingRecord)record; newRecord._xmlns = _xmlns; newRecord._clrns = _clrns; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PIMapping; } } internal string XmlNamespace { get { return _xmlns; } set {_xmlns = value; } } internal string ClrNamespace { get { return _clrns; } set { _clrns = value; } } internal short AssemblyId { get { short value = (short) _flags[_assemblyIdLowSection]; value |= (short) (_flags[_assemblyIdHighSection] << 8); return value; } set { _flags[_assemblyIdLowSection] = (short) (value & 0xff); _flags[_assemblyIdHighSection] = (short) ((value & 0xff00) >> 8); } } // Allocate space in _flags. // BitVector32 doesn't support 16 bit sections, so we have to break // it up into 2 sections. private static BitVector32.Section _assemblyIdLowSection = BitVector32.CreateSection( (short)0xff, BamlVariableSizedRecord.LastFlagsSection ); private static BitVector32.Section _assemblyIdHighSection = BitVector32.CreateSection( (short)0xff, _assemblyIdLowSection ); #if !PBTCOMPILER // This provides subclasses with a referece section to create their own section. internal new static BitVector32.Section LastFlagsSection { get { return _assemblyIdHighSection; } } #endif #endregion Properties #region Data string _xmlns; string _clrns; #endregion Data } // Common base class for variables sized records that contain a string value //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal abstract class BamlStringValueRecord : BamlVariableSizedRecord { #region Methods #if !PBTCOMPILER // LoadRecord specific data internal override void LoadRecordData(BinaryReader bamlBinaryReader) { Value = bamlBinaryReader.ReadString(); } #endif // write record specific Data. internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(Value); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlStringValueRecord newRecord = (BamlStringValueRecord)record; newRecord._value = _value; } #endif #endregion Methods #region Properties internal string Value { get { return _value; } set { _value = value; } } #endregion Properties #region Data string _value; #endregion Data } // Common methods for baml records that serve as keys in a dictionary. internal interface IBamlDictionaryKey { // Update the pointer to the Value that was written out when WriteRecordData // was first called. void UpdateValuePosition( Int32 newPosition, BinaryWriter bamlBinaryWriter); // Relative stream position in the baml stream where the value associated // with this key starts. It is relative to the end of the keys section, // or the start of the values section. Int32 ValuePosition { get; set; } // The actual key object used in the dictionary. This may be a string, // field, type or other object. object KeyObject { get; set; } // Position in the stream where ValuePosition was written. This is needed // when updating the ValuePosition. Int64 ValuePositionPosition { get; set; } // True if the value associated with this key is shared. bool Shared { get; set; } // Whether Shared was set. bool SharedSet { get; set; } #if !PBTCOMPILER object[] StaticResourceValues {get; set;} #endif } // Common interface implemented by BamlRecords that // use optimized storage for MarkupExtensions. internal interface IOptimizedMarkupExtension { short ExtensionTypeId { get; } short ValueId { get; } bool IsValueTypeExtension { get; } bool IsValueStaticExtension { get; } } // BamlRecord use in a defer loaded dictionary as the key for adding a value. // The value is a type that is refered to using a TypeID //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlDefAttributeKeyTypeRecord : BamlElementStartRecord, IBamlDictionaryKey { internal BamlDefAttributeKeyTypeRecord() { Pin(); // Don't allow this record to be recycled in the read cache. } #region Methods #if !PBTCOMPILER // LoadRecord specific data internal override void LoadRecordData(BinaryReader bamlBinaryReader) { base.LoadRecordData(bamlBinaryReader); _valuePosition = bamlBinaryReader.ReadInt32(); ((IBamlDictionaryKey)this).Shared = bamlBinaryReader.ReadBoolean(); ((IBamlDictionaryKey)this).SharedSet = bamlBinaryReader.ReadBoolean(); } #endif // Write record specific Data. internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { base.WriteRecordData(bamlBinaryWriter); _valuePositionPosition = bamlBinaryWriter.Seek(0, SeekOrigin.Current); bamlBinaryWriter.Write(_valuePosition); bamlBinaryWriter.Write(((IBamlDictionaryKey)this).Shared); bamlBinaryWriter.Write(((IBamlDictionaryKey)this).SharedSet); } // Update the pointer to the Value that was written out when WriteRecordData // was first called. At that time the true position was probably not known, // so it is written out later. Be certain to leave the passed writer pointing // to the same location it was at when this call was made. void IBamlDictionaryKey.UpdateValuePosition( Int32 newPosition, BinaryWriter bamlBinaryWriter) { Debug.Assert(_valuePositionPosition != -1, "Must call WriteRecordData before updating position"); // Use relative positions to reduce the possibility of truncation, // since Seek takes a 32 bit int, but position is a 64 bit int. Int64 existingPosition = bamlBinaryWriter.Seek(0, SeekOrigin.Current); Int32 deltaPosition = (Int32)(_valuePositionPosition-existingPosition); bamlBinaryWriter.Seek(deltaPosition, SeekOrigin.Current); bamlBinaryWriter.Write(newPosition); bamlBinaryWriter.Seek(-ValuePositionSize-deltaPosition, SeekOrigin.Current); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlDefAttributeKeyTypeRecord newRecord = (BamlDefAttributeKeyTypeRecord)record; newRecord._valuePosition = _valuePosition; newRecord._valuePositionPosition = _valuePositionPosition; newRecord._keyObject = _keyObject; newRecord._staticResourceValues = _staticResourceValues; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.DefAttributeKeyType; } } // Relative stream position in the baml stream where the value associated // with this key starts. It is relative to the end of the keys section, // or the start of the values section. Int32 IBamlDictionaryKey.ValuePosition { get { return _valuePosition; } set { _valuePosition = value; } } // The actual key used in the defer loaded dictionary. For this type of // record the key is a Type that is obtained at runtime from the base // classes TypeId object IBamlDictionaryKey.KeyObject { get { return _keyObject; } set { _keyObject = value; } } // Position in the stream where ValuePosition was written. This is needed // when updating the ValuePosition. Int64 IBamlDictionaryKey.ValuePositionPosition { get { return _valuePositionPosition; } set { _valuePositionPosition = value; } } // True if the value associated with this key is shared. bool IBamlDictionaryKey.Shared { get { return _flags[_sharedSection] == 1 ? true : false; } set { _flags[_sharedSection] = value ? 1 : 0; } } // Whether Shared was set bool IBamlDictionaryKey.SharedSet { get { return _flags[_sharedSetSection] == 1 ? true : false; } set { _flags[_sharedSetSection] = value ? 1 : 0; } } #if !PBTCOMPILER object[] IBamlDictionaryKey.StaticResourceValues { get { return _staticResourceValues; } set { _staticResourceValues = value; } } #endif // Allocate space in _flags. private static BitVector32.Section _sharedSection = BitVector32.CreateSection( 1, BamlElementStartRecord.LastFlagsSection ); private static BitVector32.Section _sharedSetSection = BitVector32.CreateSection( 1, _sharedSection ); #if !PBTCOMPILER // This provides subclasses with a referece section to create their own section. internal new static BitVector32.Section LastFlagsSection { get { return _sharedSetSection; } } #endif #endregion Properties #region Data // Size in bytes of the ValuePosition field written out to baml. This // must be in [....] with the size of _valuePosition below. internal const Int32 ValuePositionSize = 4; // Relative position in the stream where the value associated with this key starts Int32 _valuePosition; // Position in the stream where ValuePosition was written. This is needed // when updating the ValuePosition. Int64 _valuePositionPosition = -1; // Actual object key used by a dictionary. This is a Type object object _keyObject = null; #if !PBTCOMPILER object[] _staticResourceValues; #endif #endregion Data } // BamlRecord for x:Key attribute when used in a defer loaded dictionary // as the key for adding a value. The value is stored as a string. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlDefAttributeKeyStringRecord : BamlStringValueRecord, IBamlDictionaryKey { internal BamlDefAttributeKeyStringRecord() { Pin(); // Don't allow this record to be recycled in the read cache. } #region Methods #if !PBTCOMPILER // LoadRecord specific data internal override void LoadRecordData(BinaryReader bamlBinaryReader) { ValueId = bamlBinaryReader.ReadInt16(); _valuePosition = bamlBinaryReader.ReadInt32(); ((IBamlDictionaryKey)this).Shared = bamlBinaryReader.ReadBoolean(); ((IBamlDictionaryKey)this).SharedSet = bamlBinaryReader.ReadBoolean(); _keyObject = null; } #endif // Write record specific Data. internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(ValueId); _valuePositionPosition = bamlBinaryWriter.Seek(0, SeekOrigin.Current); bamlBinaryWriter.Write(_valuePosition); bamlBinaryWriter.Write(((IBamlDictionaryKey)this).Shared); bamlBinaryWriter.Write(((IBamlDictionaryKey)this).SharedSet); } // Update the pointer to the Value that was written out when WriteRecordData // was first called. At that time the true position was probably not known, // so it is written out later. Be certain to leave the passed writer pointing // to the same location it was at when this call was made. void IBamlDictionaryKey.UpdateValuePosition( Int32 newPosition, BinaryWriter bamlBinaryWriter) { Debug.Assert(_valuePositionPosition != -1, "Must call WriteRecordData before updating position"); // Use relative positions to reduce the possibility of truncation, // since Seek takes a 32 bit int, but position is a 64 bit int. Int64 existingPosition = bamlBinaryWriter.Seek(0, SeekOrigin.Current); Int32 deltaPosition = (Int32)(_valuePositionPosition-existingPosition); bamlBinaryWriter.Seek(deltaPosition, SeekOrigin.Current); bamlBinaryWriter.Write(newPosition); bamlBinaryWriter.Seek(-ValuePositionSize-deltaPosition, SeekOrigin.Current); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlDefAttributeKeyStringRecord newRecord = (BamlDefAttributeKeyStringRecord)record; newRecord._valuePosition = _valuePosition; newRecord._valuePositionPosition = _valuePositionPosition; newRecord._keyObject = _keyObject; newRecord._valueId = _valueId; newRecord._staticResourceValues = _staticResourceValues; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.DefAttributeKeyString; } } // Relative stream position in the baml stream where the value associated // with this key starts. It is relative to the end of the keys section, // or the start of the values section. Int32 IBamlDictionaryKey.ValuePosition { get { return _valuePosition; } set { _valuePosition = value; } } // True if the value associated with this key is shared. bool IBamlDictionaryKey.Shared { get { return _flags[_sharedSection] == 1 ? true : false; } set { _flags[_sharedSection] = value ? 1 : 0; } } // Whether Shared was set bool IBamlDictionaryKey.SharedSet { get { return _flags[_sharedSetSection] == 1 ? true : false; } set { _flags[_sharedSetSection] = value ? 1 : 0; } } // Allocate space in _flags. private static BitVector32.Section _sharedSection = BitVector32.CreateSection( 1, BamlStringValueRecord.LastFlagsSection ); private static BitVector32.Section _sharedSetSection = BitVector32.CreateSection( 1, _sharedSection ); #if !PBTCOMPILER // This provides subclasses with a referece section to create their own section. internal new static BitVector32.Section LastFlagsSection { get { return _sharedSetSection; } } #endif // The following are NOT written out to BAML but are cached at runtime // The string value translated into a key object. The string may represent // a type, field, or other object that can be translated into an object using // using the Mapper. object IBamlDictionaryKey.KeyObject { get { return _keyObject; } set { _keyObject = value; } } // Position in the stream where ValuePosition was written. This is needed // when updating the ValuePosition. Int64 IBamlDictionaryKey.ValuePositionPosition { get { return _valuePositionPosition; } set { _valuePositionPosition = value; } } internal Int16 ValueId { get { return _valueId; } set { _valueId = value; } } #if !PBTCOMPILER object[] IBamlDictionaryKey.StaticResourceValues { get { return _staticResourceValues; } set { _staticResourceValues = value; } } #endif #endregion Properties #region Data // Size in bytes of the ValuePosition field written out to baml. This // must be in [....] with the size of _valuePosition below. internal const Int32 ValuePositionSize = 4; // Relative position in the stream where the value associated with this key starts Int32 _valuePosition; // Position in the stream where ValuePosition was written. This is needed // when updating the ValuePosition. Int64 _valuePositionPosition = -1; // Actual object key used by a dictionary. This is the Value string // after conversion. object _keyObject = null; Int16 _valueId; #if !PBTCOMPILER object[] _staticResourceValues; #endif #endregion Data } // BamlRecord for x:Whatever attribute //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlDefAttributeRecord : BamlStringValueRecord { #region Methods #if !PBTCOMPILER // LoadRecord specific data internal override void LoadRecordData(BinaryReader bamlBinaryReader) { Value = bamlBinaryReader.ReadString(); NameId = bamlBinaryReader.ReadInt16(); Name = null; } #endif // write record specific Data. internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(Value); bamlBinaryWriter.Write(NameId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlDefAttributeRecord newRecord = (BamlDefAttributeRecord)record; newRecord._name = _name; newRecord._nameId = _nameId; newRecord._attributeUsage = _attributeUsage; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.DefAttribute; } } // The following is written out the baml file. internal Int16 NameId { get { return _nameId; } set { _nameId = value; } } // The following are cached locally, but not written to baml. internal string Name { #if !PBTCOMPILER get { return _name; } #endif set { _name = value; } } // Some attributes have special usage, such as setting the XmlLang and XmlSpace // strings in the parser context. This is flagged with this property internal BamlAttributeUsage AttributeUsage { #if !PBTCOMPILER get { return _attributeUsage; } #endif set { _attributeUsage = value; } } #endregion Properties #if !PBTCOMPILER public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0} nameId({1}) is '{2}' usage={3}", RecordType, NameId, Name, AttributeUsage); } #endif #region Data string _name; Int16 _nameId; BamlAttributeUsage _attributeUsage; #endregion Data } // BamlRecord for PresentationOptions:Whatever attribute //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPresentationOptionsAttributeRecord : BamlStringValueRecord { #region Methods #if !PBTCOMPILER // LoadRecord specific data internal override void LoadRecordData(BinaryReader bamlBinaryReader) { Value = bamlBinaryReader.ReadString(); NameId = bamlBinaryReader.ReadInt16(); Name = null; } #endif // write record specific Data. internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(Value); bamlBinaryWriter.Write(NameId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlPresentationOptionsAttributeRecord newRecord = (BamlPresentationOptionsAttributeRecord)record; newRecord._name = _name; newRecord._nameId = _nameId; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PresentationOptionsAttribute; } } // The following is written out the baml file. internal Int16 NameId { get { return _nameId; } set { _nameId = value; } } // The following are cached locally, but not written to baml. internal string Name { #if !PBTCOMPILER get { return _name; } #endif set { _name = value; } } #endregion Properties #if !PBTCOMPILER public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0} nameId({1}) is '{2}' ", RecordType, NameId, Name); } #endif #region Data string _name; Int16 _nameId; #endregion Data } // // BamlPropertyComplexStartRecord is for Complex DependencyProperty declarations // in markup, where the actual type and value is determined by subsequent records. // //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyComplexStartRecord : BamlRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { AttributeId = bamlBinaryReader.ReadInt16(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(AttributeId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlPropertyComplexStartRecord newRecord = (BamlPropertyComplexStartRecord)record; newRecord._attributeId = _attributeId; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyComplexStart; } } internal short AttributeId { get { return _attributeId; } set { _attributeId = value; } } internal override Int32 RecordSize { get { return 2; } set { Debug.Assert (value == -1, "Wrong size set for complex prop record"); } } #endregion Properties #if !PBTCOMPILER public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0} attr({1})", RecordType, _attributeId); } #endif #region Data short _attributeId = -1; #endregion Data } // // BamlPropertyStringReferenceRecord is for Property values that are written // out as references into the string table. // //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyStringReferenceRecord : BamlPropertyComplexStartRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { AttributeId = bamlBinaryReader.ReadInt16(); StringId = bamlBinaryReader.ReadInt16(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(AttributeId); bamlBinaryWriter.Write(StringId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlPropertyStringReferenceRecord newRecord = (BamlPropertyStringReferenceRecord)record; newRecord._stringId = _stringId; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyStringReference; } } internal short StringId { get { return _stringId; } #if !PBTCOMPILER set { _stringId = value; } #endif } internal override Int32 RecordSize { get { return 4; } set { Debug.Assert (value == -1, "Wrong size set for complex prop record"); } } #endregion Properties #region Data short _stringId = 0; #endregion Data } // // BamlPropertyTypeReferenceRecord is for Property values that are written // out as references into the type table. So the property value is a 'Type' object. // //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyTypeReferenceRecord : BamlPropertyComplexStartRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { AttributeId = bamlBinaryReader.ReadInt16(); TypeId = bamlBinaryReader.ReadInt16(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(AttributeId); bamlBinaryWriter.Write(TypeId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlPropertyTypeReferenceRecord newRecord = (BamlPropertyTypeReferenceRecord)record; newRecord._typeId = _typeId; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyTypeReference; } } internal short TypeId { get { return _typeId; } set { _typeId = value; } } internal override Int32 RecordSize { get { return 4; } set { Debug.Assert (value == -1, "Wrong size set for complex prop record"); } } #endregion Properties #region Data short _typeId = 0; #endregion Data } // // BamlPropertyWithConverterRecord information for property with custom type converter // //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyWithConverterRecord : BamlPropertyRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { base.LoadRecordData(bamlBinaryReader); ConverterTypeId = bamlBinaryReader.ReadInt16(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { base.WriteRecordData(bamlBinaryWriter); bamlBinaryWriter.Write(ConverterTypeId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlPropertyWithConverterRecord newRecord = (BamlPropertyWithConverterRecord)record; newRecord._converterTypeId = _converterTypeId; } #endif #endregion Methods #region Properties // The following are stored in the baml stream // ID of this type converter. Referenced in other baml records where a // Type is needed. internal short ConverterTypeId { get { return _converterTypeId; } set { _converterTypeId = value; } } // Additional properties not stored in the baml stream internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyWithConverter; } } #endregion Properties #region Data short _converterTypeId = 0; #endregion Data } // // BamlPropertyRecord is for DependencyProperty values that are written // out as strings. // //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyRecord : BamlStringValueRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { AttributeId = bamlBinaryReader.ReadInt16(); Value = bamlBinaryReader.ReadString(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(AttributeId); bamlBinaryWriter.Write(Value); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlPropertyRecord newRecord = (BamlPropertyRecord)record; newRecord._attributeId = _attributeId; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.Property; } } internal short AttributeId { get { return _attributeId; } set { _attributeId = value; } } #endregion Properties #if !PBTCOMPILER public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0} attr({1}) <== '{2}'", RecordType, _attributeId, Value); } #endif #region Data short _attributeId = -1; #endregion Data } // // BamlPropertyWithExtensionRecord is for property values that are Markup extensions // with a single param member that are written out as attributeIds. // //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyWithExtensionRecord : BamlRecord, IOptimizedMarkupExtension { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { AttributeId = bamlBinaryReader.ReadInt16(); short extensionTypeId = bamlBinaryReader.ReadInt16(); ValueId = bamlBinaryReader.ReadInt16(); // The upper 4 bits of the ExtensionTypeId are used as flags _extensionTypeId = (short)(extensionTypeId & ExtensionIdMask); IsValueTypeExtension = (extensionTypeId & TypeExtensionValueMask) == TypeExtensionValueMask; IsValueStaticExtension = (extensionTypeId & StaticExtensionValueMask) == StaticExtensionValueMask; } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(AttributeId); short extensionTypeId = ExtensionTypeId; if (IsValueTypeExtension) { extensionTypeId |= TypeExtensionValueMask; } else if (IsValueStaticExtension) { extensionTypeId |= StaticExtensionValueMask; } bamlBinaryWriter.Write(extensionTypeId); bamlBinaryWriter.Write(ValueId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlPropertyWithExtensionRecord newRecord = (BamlPropertyWithExtensionRecord)record; newRecord._attributeId = _attributeId; newRecord._extensionTypeId = _extensionTypeId; newRecord._valueId = _valueId; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyWithExtension; } } // Id of the property whose value is the simple ME internal short AttributeId { get { return _attributeId; } set { _attributeId = value; } } // KnownElement Id of the MarkupExtension public short ExtensionTypeId { get { return _extensionTypeId; } set { // we shouldn't ever be intruding on the flags portion of the ExtensionTypeId Debug.Assert(value <= ExtensionIdMask); _extensionTypeId = value; } } // For StaticExtension: AttributeId of a member // For TemplateBindingExtension: AttributeId of a DependencyProperty // For a DynamicResourceExtension: // StringId if the value is a string // TypeId if the value is a TypeExtension // AttributeId of the member if the value is a StaticExtension public short ValueId { get { return _valueId; } set { _valueId = value; } } internal override Int32 RecordSize { get { return 6; } set { Debug.Assert(value == -1, "Wrong size set for complex prop record"); } } // For DynamicResourceExtension, if the value is itself a simple TypeExtension public bool IsValueTypeExtension { get { return _flags[_isValueTypeExtensionSection] == 1 ? true : false; } set { _flags[_isValueTypeExtensionSection] = value ? 1 : 0; } } // For DynamicResourceExtension, if the value is itself a simple StaticExtension public bool IsValueStaticExtension { get { return _flags[_isValueStaticExtensionSection] == 1 ? true : false; } set { _flags[_isValueStaticExtensionSection] = value ? 1 : 0; } } // Allocate space in _flags. private static BitVector32.Section _isValueTypeExtensionSection = BitVector32.CreateSection(1, BamlRecord.LastFlagsSection); private static BitVector32.Section _isValueStaticExtensionSection = BitVector32.CreateSection(1, _isValueTypeExtensionSection); #if !PBTCOMPILER // This provides subclasses with a referece section to create their own section. internal new static BitVector32.Section LastFlagsSection { get { return _isValueStaticExtensionSection; } } public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0} attr({1}) extn({2}) valueId({3})", RecordType, _attributeId, _extensionTypeId, _valueId); } #endif #endregion Properties #region Data short _attributeId = -1; short _extensionTypeId = 0; short _valueId = 0; private static readonly short ExtensionIdMask = 0x0FFF; private static readonly short TypeExtensionValueMask = 0x4000; private static readonly short StaticExtensionValueMask = 0x2000; #endregion Data } // // BamlPropertyCustomWriteInfoRecord is for DependencyProperty values that support // custom Avalon serialization. The property value objects write directly onto // the BAML stream in whatever format they understand. This record is used only // during BAML write time. // //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyCustomWriteInfoRecord : BamlPropertyCustomRecord { internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { int writePositionStart = (int)bamlBinaryWriter.Seek(0, SeekOrigin.Current); short serializerTypeId = SerializerTypeId; bamlBinaryWriter.Write(AttributeId); if (serializerTypeId == (short)KnownElements.DependencyPropertyConverter) { // There is no need to actually use a real Converter here since we already have the // DP value as an AttributeInfoId. // if ValueMemberName exists then remember that the ValueId is a TypeId of the // type that declares ValueMemberName, so that it can be resolved correctly at // load time. if (ValueMemberName != null) { bamlBinaryWriter.Write((short)(serializerTypeId | TypeIdValueMask)); } else { bamlBinaryWriter.Write(serializerTypeId); } // if ValueMemberName does not exist, ValueId is a KnownProperty Id // else it is a TypeId of the declaring type. bamlBinaryWriter.Write(ValueId); // Write out the ValueMemberName if it exists if (ValueMemberName != null) { bamlBinaryWriter.Write(ValueMemberName); } return; } bamlBinaryWriter.Write(serializerTypeId); bool converted = false; // If we have an enum or a bool, do conversion to custom binary data here, // since we do not have a serializer associated with these types. if (ValueType != null && ValueType.IsEnum) { uint uintValue = 0; string [] enumValues = Value.Split(new Char[] { ',' }); // if the Enum is a flag, then resolve each flag value in the enum value string. foreach (string enumValue in enumValues) { FieldInfo enumField = ValueType.GetField(enumValue.Trim(), BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase); if (enumField != null) { // get the raw va;ue of the enum field and convert to a uint. object rawEnumValue = enumField.GetRawConstantValue(); uintValue += (uint)Convert.ChangeType(rawEnumValue, typeof(uint), TCH.EnglishUSCulture); converted = true; } else { converted = false; break; } } if (converted) { bamlBinaryWriter.Write(uintValue); } } else if (ValueType == typeof(Boolean)) { TypeConverter boolConverter = TypeDescriptor.GetConverter(typeof(Boolean)); object convertedValue = boolConverter.ConvertFromString(TypeContext, TCH.EnglishUSCulture, Value); bamlBinaryWriter.Write((byte)Convert.ChangeType(convertedValue, typeof(byte), TCH.EnglishUSCulture)); converted = true; } else if (SerializerType == typeof(XamlBrushSerializer)) { XamlSerializer serializer = new XamlBrushSerializer(); // If we custom serialize this particular value at this point, then see // if it can convert. // NOTE: This is sensitive to changes in the BamlRecordWriter and // BamlRecordManager code and must be kept in [....] with them... converted = serializer.ConvertStringToCustomBinary(bamlBinaryWriter, Value); } else if (SerializerType == typeof(XamlPoint3DCollectionSerializer)) { XamlSerializer serializer = new XamlPoint3DCollectionSerializer(); // If we custom serialize this particular value at this point, then see // if it can convert. // NOTE: This is sensitive to changes in the BamlRecordWriter and // BamlRecordManager code and must be kept in [....] with them... converted = serializer.ConvertStringToCustomBinary(bamlBinaryWriter, Value); } else if (SerializerType == typeof(XamlVector3DCollectionSerializer)) { XamlSerializer serializer = new XamlVector3DCollectionSerializer(); // If we custom serialize this particular value at this point, then see // if it can convert. // NOTE: This is sensitive to changes in the BamlRecordWriter and // BamlRecordManager code and must be kept in [....] with them... converted = serializer.ConvertStringToCustomBinary(bamlBinaryWriter, Value); } else if (SerializerType == typeof(XamlPointCollectionSerializer)) { XamlSerializer serializer = new XamlPointCollectionSerializer(); // If we custom serialize this particular value at this point, then see // if it can convert. // NOTE: This is sensitive to changes in the BamlRecordWriter and // BamlRecordManager code and must be kept in [....] with them... converted = serializer.ConvertStringToCustomBinary(bamlBinaryWriter, Value); } else if (SerializerType == typeof(XamlInt32CollectionSerializer)) { XamlSerializer serializer = new XamlInt32CollectionSerializer(); // If we custom serialize this particular value at this point, then see // if it can convert. // NOTE: This is sensitive to changes in the BamlRecordWriter and // BamlRecordManager code and must be kept in [....] with them... converted = serializer.ConvertStringToCustomBinary(bamlBinaryWriter, Value); } else if (SerializerType == typeof(XamlPathDataSerializer)) { XamlSerializer serializer = new XamlPathDataSerializer(); // If we custom serialize this particular value at this point, then see // if it can convert. // NOTE: This is sensitive to changes in the BamlRecordWriter and // BamlRecordManager code and must be kept in [....] with them... converted = serializer.ConvertStringToCustomBinary(bamlBinaryWriter, Value); } if (!converted) { throw new XamlParseException(SR.Get(SRID.ParserBadString, Value, ValueType.Name)); } } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlPropertyCustomWriteInfoRecord newRecord = (BamlPropertyCustomWriteInfoRecord)record; newRecord._valueId = _valueId; newRecord._valueType = _valueType; newRecord._value = _value; newRecord._valueMemberName = _valueMemberName; newRecord._serializerType = _serializerType; newRecord._typeContext = _typeContext; } #endif // The KnownProperty Id of the Value, if it is a property and can be converted into one, // or the TypeId of the owner of the property value internal short ValueId { get { return _valueId; } set { _valueId = value; } } // If ValueId is a TypeId, then this holds the name of the member. internal string ValueMemberName { get { return _valueMemberName; } set { _valueMemberName = value; } } // The following properties are NOT written to the BAML stream. // Type of this property internal Type ValueType { get { return _valueType; } set { _valueType = value; } } // The string Value of the property. internal string Value { get { return _value; } set { _value = value; } } // Type of the XamlSerializer associated with this property. Null // if this type is custom serialized by the parser itself. internal Type SerializerType { get { return _serializerType; } set { _serializerType = value; } } // Context used for type conversion of built in types. internal ITypeDescriptorContext TypeContext { get { return _typeContext; } set { _typeContext = value; } } short _valueId; Type _valueType; string _value; string _valueMemberName; Type _serializerType; ITypeDescriptorContext _typeContext; } // // BamlPropertyCustomRecord is for DependencyProperty values that support // custom Avalon serialization. This record is used only during BAML load. // The property value objects are read directly from the BAML stream by the // custom binary serializer for the property. // //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyCustomRecord : BamlVariableSizedRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { AttributeId = bamlBinaryReader.ReadInt16(); short serializerTypeId = bamlBinaryReader.ReadInt16(); IsValueTypeId = (serializerTypeId & TypeIdValueMask) == TypeIdValueMask; if (IsValueTypeId) { serializerTypeId &= (short)(~TypeIdValueMask); } SerializerTypeId = serializerTypeId; ValueObjectSet = false; IsRawEnumValueSet = false; _valueObject = null; // ValueObject and ValueObject are not set until BamlRecordReader.ReadPropertyCustomRecord // because the Mapper is needed for custom DPs // NOTE: above may no longer true, so this could be potentially changed to be in [....] with // other record. Needs more investigation. } // Read the binary data using the passed reader and use that to set the ValueObject. internal object GetCustomValue(BinaryReader reader, Type propertyType, short serializerId, BamlRecordReader bamlRecordReader) { Debug.Assert(!ValueObjectSet); // Handle enums and bools here directly. // Otherwise call the known custom serializers directly. switch (serializerId) { case (short)KnownElements.EnumConverter: uint enumBits; if (_valueObject == null) { // if no raw value has been read in yet, read it now // from the baml stream. enumBits = reader.ReadUInt32(); } else { // raw value has been read in earlier, so try to resolve into // an actual enum value now. enumBits = (uint)_valueObject; } if (propertyType.IsEnum) { // property Type is an enum, so raw value can be resolved now. _valueObject = Enum.ToObject(propertyType, enumBits); ValueObjectSet = true; IsRawEnumValueSet = false; } else { // property Type is not available yet, so raw value cannot // be resolved now. Store it and try later. _valueObject = enumBits; ValueObjectSet = false; IsRawEnumValueSet = true; } return _valueObject; case (short)KnownElements.BooleanConverter: byte boolByte = reader.ReadByte(); _valueObject = boolByte == 1; break; case (short)KnownElements.XamlBrushSerializer: // Don't bother creating a XamlBrushSerializer instance & calling ConvertCustomBinaryToObject // on it since that just calls SCB directly liek below. This saves big on perf. _valueObject = SolidColorBrush.DeserializeFrom(reader, bamlRecordReader.TypeConvertContext); break; case (short)KnownElements.XamlPathDataSerializer: _valueObject = XamlPathDataSerializer.StaticConvertCustomBinaryToObject(reader); break; case (short)KnownElements.XamlPoint3DCollectionSerializer: _valueObject = XamlPoint3DCollectionSerializer.StaticConvertCustomBinaryToObject(reader); break; case (short)KnownElements.XamlVector3DCollectionSerializer: _valueObject = XamlVector3DCollectionSerializer.StaticConvertCustomBinaryToObject(reader); break; case (short)KnownElements.XamlPointCollectionSerializer: _valueObject = XamlPointCollectionSerializer.StaticConvertCustomBinaryToObject(reader); break; case (short)KnownElements.XamlInt32CollectionSerializer: _valueObject = XamlInt32CollectionSerializer.StaticConvertCustomBinaryToObject(reader); break; default: Debug.Assert (false, "Unknown custom serializer"); return null; } ValueObjectSet = true; return _valueObject; } internal override void Copy(BamlRecord record) { base.Copy(record); BamlPropertyCustomRecord newRecord = (BamlPropertyCustomRecord)record; newRecord._valueObject = _valueObject; newRecord._attributeId = _attributeId; newRecord._serializerTypeId = _serializerTypeId; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyCustom; } } internal short AttributeId { get { return _attributeId; } set { _attributeId = value; } } // ID of this serializer type. Referenced in other baml records where a // Type is needed. internal short SerializerTypeId { get { return _serializerTypeId; } set { _serializerTypeId = value; } } // The following properties are NOT written to the BAML stream. #if !PBTCOMPILER // Value of the converted object. internal object ValueObject { get { return _valueObject; } set { _valueObject = value; } } // Return true if GetCustomValue has been called, indicating that // a conversion from binary custom data to a ValueObject has occurred. internal bool ValueObjectSet { get { return _flags[_isValueSetSection] == 1 ? true : false; } set { _flags[_isValueSetSection] = value ? 1 : 0; } } internal bool IsValueTypeId { get { return _flags[_isValueTypeIdSection] == 1 ? true : false; } set { _flags[_isValueTypeIdSection] = value ? 1 : 0; } } // true if only the raw value of enum has been read as it cannot yet be // converted into an enum as the Type is not available yet. internal bool IsRawEnumValueSet { get { return _flags[_isRawEnumValueSetSection] == 1 ? true : false; } set { _flags[_isRawEnumValueSetSection] = value ? 1 : 0; } } object _valueObject; // Allocate space in _flags. private static BitVector32.Section _isValueSetSection = BitVector32.CreateSection(1, BamlVariableSizedRecord.LastFlagsSection); // Allocate space in _flags. private static BitVector32.Section _isValueTypeIdSection = BitVector32.CreateSection(1, _isValueSetSection); // Allocate space in _flags. private static BitVector32.Section _isRawEnumValueSetSection = BitVector32.CreateSection(1, _isValueTypeIdSection); // This provides subclasses with a referece section to create their own section. internal new static BitVector32.Section LastFlagsSection { get { return _isRawEnumValueSetSection; } } #endif #endregion Properties #region Data internal static readonly short TypeIdValueMask = 0x4000; short _attributeId = 0; short _serializerTypeId = 0; #endregion Data } //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyArrayEndRecord : BamlRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyArrayEnd; } } #endregion Properties } //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlConstructorParametersStartRecord : BamlRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.ConstructorParametersStart; } } #endregion Properties } //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlConstructorParametersEndRecord : BamlRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.ConstructorParametersEnd; } } #endregion Properties } //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlConstructorParameterTypeRecord : BamlRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { TypeId = bamlBinaryReader.ReadInt16(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(TypeId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlConstructorParameterTypeRecord newRecord = (BamlConstructorParameterTypeRecord)record; newRecord._typeId = _typeId; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.ConstructorParameterType; } } internal short TypeId { get { return _typeId; } set { _typeId = value; } } internal override Int32 RecordSize { get { return 2; } set { Debug.Assert (value == -1, "Wrong size set for complex prop record"); } } #endregion Properties #region Data short _typeId = 0; #endregion Data } //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyIListEndRecord : BamlRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyIListEnd; } } #endregion Properties } //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyIDictionaryEndRecord : BamlRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyIDictionaryEnd; } } #endregion Properties } //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyComplexEndRecord : BamlRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyComplexEnd; } } #endregion Properties } //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyArrayStartRecord : BamlPropertyComplexStartRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyArrayStart; } } #endregion Properties } //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyIListStartRecord : BamlPropertyComplexStartRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyIListStart; } } #endregion Properties } //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyIDictionaryStartRecord : BamlPropertyComplexStartRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyIDictionaryStart; } } #endregion Properties } //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlRoutedEventRecord : BamlStringValueRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { AttributeId = bamlBinaryReader.ReadInt16(); Value = bamlBinaryReader.ReadString(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(AttributeId); bamlBinaryWriter.Write(Value); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlRoutedEventRecord newRecord = (BamlRoutedEventRecord)record; newRecord._attributeId = _attributeId; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.RoutedEvent; } } internal short AttributeId { get { return _attributeId; } #if !PBTCOMPILER set { _attributeId = value; } #endif } #endregion Properties #region Data short _attributeId = -1; #endregion Data } // A section of literal content. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlLiteralContentRecord : BamlStringValueRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { Value = bamlBinaryReader.ReadString(); // Int32 _lineNumber = bamlBinaryReader.ReadInt32(); Int32 _linePosition = bamlBinaryReader.ReadInt32(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(Value); // bamlBinaryWriter.Write((Int32)0); bamlBinaryWriter.Write((Int32)0); } #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.LiteralContent; } } #endregion Properties } // An record for the connection id that the (Style)BamlRecordReader uses to // hookup an ID or event on any element in the object tree or Style visual tree. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlConnectionIdRecord : BamlRecord { #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { ConnectionId = bamlBinaryReader.ReadInt32(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(ConnectionId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlConnectionIdRecord newRecord = (BamlConnectionIdRecord)record; newRecord._connectionId = _connectionId; } #endif internal override BamlRecordType RecordType { get { return BamlRecordType.ConnectionId; } } // Id of the type of this object internal Int32 ConnectionId { get { return _connectionId; } set { _connectionId = value; } } internal override Int32 RecordSize { get { return 4; } set { Debug.Assert(value == -1, "Wrong size set for element record"); } } Int32 _connectionId = -1; } // An object record in the object tree. This can be a CLR // object or a DependencyObject. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlElementStartRecord : BamlRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { TypeId = bamlBinaryReader.ReadInt16(); byte flags = bamlBinaryReader.ReadByte(); CreateUsingTypeConverter = (flags & 1) != 0; IsInjected = (flags & 2) != 0; } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(TypeId); byte flags = (byte)((CreateUsingTypeConverter ? 1 : 0) | (IsInjected ? 2 : 0)); bamlBinaryWriter.Write(flags); } #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.ElementStart; } } // Id of the type of this object internal short TypeId { get { short value = (short) _flags[_typeIdLowSection]; value |= (short) (_flags[_typeIdHighSection] << 8); return value; } set { _flags[_typeIdLowSection] = (short) (value & 0xff); _flags[_typeIdHighSection] = (short) ((value & 0xff00) >> 8); } } // Whether this object instance is expected to be created via TypeConverter internal bool CreateUsingTypeConverter { get { return _flags[_useTypeConverter] == 1 ? true : false; } set { _flags[_useTypeConverter] = value ? 1 : 0; } } // Whether this element start record is just an injected tag that should not be processed internal bool IsInjected { get { return _flags[_isInjected] == 1 ? true : false; } set { _flags[_isInjected] = value ? 1 : 0; } } internal override Int32 RecordSize { get { return 3; } set { Debug.Assert(value == -1, "Wrong size set for element record"); } } #endregion Properties #if !PBTCOMPILER public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0} typeId={1}", RecordType, GetTypeName(TypeId)); } #endif // Allocate space in _flags. // BitVector32 doesn't support 16 bit sections, so we have to break // it up into 2 sections. private static BitVector32.Section _typeIdLowSection = BitVector32.CreateSection( (short)0xff, BamlRecord.LastFlagsSection ); private static BitVector32.Section _typeIdHighSection = BitVector32.CreateSection( (short)0xff, _typeIdLowSection ); private static BitVector32.Section _useTypeConverter = BitVector32.CreateSection( 1, _typeIdHighSection ); private static BitVector32.Section _isInjected = BitVector32.CreateSection( 1, _useTypeConverter ); // This provides subclasses with a referece section to create their own section. internal new static BitVector32.Section LastFlagsSection { get { return _isInjected; } } } //+--------------------------------------------------------------------------------------------------------------- // // BamlNamedElementStartRecord // // This is a BamlElementStartRecord that also carries an element name. // // This is currently internal, used only for templates. The original intent for this record was that // it become the new design for named objects; any object with an x:Name set, would have that name // incorporated into the element start record. But that design did not happen, instead the // property attribute are re-ordered such that the name always immediately follows the element // start record. So this should be removed, and the template code updated accordingly. (And in fact, // the template design should be updated so as not to be reliant on naming, as that is too fragile.) // //+---------------------------------------------------------------------------------------------------------------- #if !PBTCOMPILER internal class BamlNamedElementStartRecord : BamlElementStartRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { TypeId = bamlBinaryReader.ReadInt16(); RuntimeName = bamlBinaryReader.ReadString(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(TypeId); if( RuntimeName != null ) { bamlBinaryWriter.Write(RuntimeName); } } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlNamedElementStartRecord newRecord = (BamlNamedElementStartRecord)record; newRecord._isTemplateChild = _isTemplateChild; newRecord._runtimeName = _runtimeName; } #endif #endregion Methods #region Properties internal string RuntimeName { get { return _runtimeName; } set { _runtimeName = value; } } // This flag is used by templates to indicate that an ElementStart // record is for an object that will be a template child. We had to add // this to allow some validation during template application. This isn't // a good solution, because we shouldn't have this record understanding // template children. But the long-term plan is to break the template design // away from a dependence on names, at which point this whole BamlNamedElementStartRecord // will go away. private bool _isTemplateChild = false; internal bool IsTemplateChild { get { return _isTemplateChild; } set { _isTemplateChild = value; } } #endregion Properties #region Data // Id of the type of this object string _runtimeName = null; #endregion Data } #endif // Marks a block that has deferable content. This record contains the size // of the deferable section, excluding the start and end records themselves. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlDeferableContentStartRecord : BamlRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { ContentSize = bamlBinaryReader.ReadInt32(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { _contentSizePosition = bamlBinaryWriter.Seek(0, SeekOrigin.Current); bamlBinaryWriter.Write(ContentSize); } // Update the size of the content contained between the end of the start // record and the beginning of the end record. The size of the content is // usually not known when the start record is written out. internal void UpdateContentSize( Int32 contentSize, BinaryWriter bamlBinaryWriter) { Debug.Assert(_contentSizePosition != -1, "Must call WriteRecordData before updating content size"); // Use relative positions to reduce the possibility of truncation, // since Seek takes a 32 bit int, but position is a 64 bit int. Int64 existingPosition = bamlBinaryWriter.Seek(0, SeekOrigin.Current); Int32 deltaPosition = (Int32)(_contentSizePosition-existingPosition); bamlBinaryWriter.Seek(deltaPosition, SeekOrigin.Current); bamlBinaryWriter.Write(contentSize); bamlBinaryWriter.Seek((int)(-ContentSizeSize-deltaPosition), SeekOrigin.Current); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlDeferableContentStartRecord newRecord = (BamlDeferableContentStartRecord)record; newRecord._contentSize = _contentSize; newRecord._contentSizePosition = _contentSizePosition; newRecord._valuesBuffer = _valuesBuffer; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.DeferableContentStart; } } internal Int32 ContentSize { get { return _contentSize; } #if !PBTCOMPILER set { _contentSize = value; } #endif } internal override Int32 RecordSize { get { return 4; } set { Debug.Assert(value == -1, "Wrong size set for element record"); } } #if !PBTCOMPILER ////// For the case of a ResourceDictionary inside template content, we read /// the dictionary values into a byte array while creating the template /// content. Later during template instantiation when the dictionary instance /// is created we use this buffer to create a memory stream so that the /// ResourceDictionary can use it to RealizeDeferredContent. This is required /// because at template instantiation time we do not have a stream to work with. /// The reader operates on a linked list of BamlRecords. /// internal byte[] ValuesBuffer { get { return _valuesBuffer; } set { _valuesBuffer = value; } } #endif #endregion Properties #region Data // Size of the ContentSize field written out to the baml stream. This // must be kept in [....] with the size of the _contentSize field. const Int64 ContentSizeSize = 4; // Size of the content between the end of the start record and the // beginning of the end record for this element. Int32 _contentSize = - 1; // Absolute position in the stream where ContentSize is written. Int64 _contentSizePosition = -1; #if !PBTCOMPILER byte[] _valuesBuffer; #endif #endregion Data } //+--------------------------------------------------------------------------------------------------------------- // // BamlStaticResourceStartRecord // // This record marks the start of a StaticResourceExtension within the header for a deferred section. // //+---------------------------------------------------------------------------------------------------------------- internal class BamlStaticResourceStartRecord : BamlElementStartRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.StaticResourceStart; } } #endregion Properties } //+---------------------------------------------------------------------------------------------------------------- // // BamlStaticResourceEndRecord // // This record marks the end of a StaticResourceExtension within the header for a deferred section. // //+--------------------------------------------------------------------------------------------------------------- internal class BamlStaticResourceEndRecord : BamlElementEndRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.StaticResourceEnd; } } #endregion Properties } //+---------------------------------------------------------------------------------------------------------------- // // BamlOptimizedStaticResourceRecord // // This record represents an optimized StaticResourceExtension within the header for a deferred section. // //+--------------------------------------------------------------------------------------------------------------- internal class BamlOptimizedStaticResourceRecord : BamlRecord, IOptimizedMarkupExtension { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { byte flags = bamlBinaryReader.ReadByte(); ValueId = bamlBinaryReader.ReadInt16(); IsValueTypeExtension = (flags & TypeExtensionValueMask) != 0; IsValueStaticExtension = (flags & StaticExtensionValueMask) != 0; } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { byte flags = 0; if (IsValueTypeExtension) { flags |= TypeExtensionValueMask; } else if (IsValueStaticExtension) { flags |= StaticExtensionValueMask; } bamlBinaryWriter.Write(flags); bamlBinaryWriter.Write(ValueId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlOptimizedStaticResourceRecord newRecord = (BamlOptimizedStaticResourceRecord)record; newRecord._valueId = _valueId; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.OptimizedStaticResource; } } public short ExtensionTypeId { get { return (short)KnownElements.StaticResourceExtension; } } // StringId if the value is a string // TypeId if the value is a TypeExtension // AttributeId of the member if the value is a StaticExtension public short ValueId { get { return _valueId; } set { _valueId = value; } } internal override Int32 RecordSize { get { return 3; } set { Debug.Assert(value == -1, "Wrong size set for complex prop record"); } } // If the value is itself a simple TypeExtension public bool IsValueTypeExtension { get { return _flags[_isValueTypeExtensionSection] == 1 ? true : false; } set { _flags[_isValueTypeExtensionSection] = value ? 1 : 0; } } // If the value is itself a simple StaticExtension public bool IsValueStaticExtension { get { return _flags[_isValueStaticExtensionSection] == 1 ? true : false; } set { _flags[_isValueStaticExtensionSection] = value ? 1 : 0; } } #endregion Properties #region Data short _valueId = 0; private static readonly byte TypeExtensionValueMask = 0x01; private static readonly byte StaticExtensionValueMask = 0x02; // Allocate space in _flags. private static BitVector32.Section _isValueTypeExtensionSection = BitVector32.CreateSection(1, BamlRecord.LastFlagsSection); private static BitVector32.Section _isValueStaticExtensionSection = BitVector32.CreateSection(1, _isValueTypeExtensionSection); // This provides subclasses with a referece section to create their own section. internal new static BitVector32.Section LastFlagsSection { get { return _isValueStaticExtensionSection; } } #if !PBTCOMPILER public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0} extn(StaticResourceExtension) valueId({1})", RecordType, _valueId); } #endif #endregion Data } //+--------------------------------------------------------------------------------------------------------------- // // BamlStaticResourceIdRecord // // This BamlRecord is an identifier for a StaticResourceExtension within the header for a deferred section. // //+--------------------------------------------------------------------------------------------------------------- internal class BamlStaticResourceIdRecord : BamlRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { StaticResourceId = bamlBinaryReader.ReadInt16(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(StaticResourceId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlStaticResourceIdRecord newRecord = (BamlStaticResourceIdRecord)record; newRecord._staticResourceId = _staticResourceId; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.StaticResourceId; } } internal override Int32 RecordSize { get { return 2; } set { Debug.Assert(value == -1, "Wrong size set for complex prop record"); } } internal short StaticResourceId { get { return _staticResourceId; } set { _staticResourceId = value; } } #endregion Properties #region Data short _staticResourceId = -1; #if !PBTCOMPILER public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0} staticResourceId({1})", RecordType, StaticResourceId); } #endif #endregion Data } //+---------------------------------------------------------------------------------------------------------------- // // BamlPropertyWithStaticResourceIdRecord // // This BamlRecord represents a BamlPropertyRecord with a StaticResourceId as place holder for // a StaticResourceExtension within a deferred section. // //+--------------------------------------------------------------------------------------------------------------- internal class BamlPropertyWithStaticResourceIdRecord : BamlStaticResourceIdRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { AttributeId = bamlBinaryReader.ReadInt16(); StaticResourceId = bamlBinaryReader.ReadInt16(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(AttributeId); bamlBinaryWriter.Write(StaticResourceId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlPropertyWithStaticResourceIdRecord newRecord = (BamlPropertyWithStaticResourceIdRecord)record; newRecord._attributeId = _attributeId; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyWithStaticResourceId; } } internal override Int32 RecordSize { get { return 4; } set { Debug.Assert(value == -1, "Wrong size set for complex prop record"); } } // Id of the property whose value is the simple SR internal short AttributeId { get { return _attributeId; } set { _attributeId = value; } } #endregion Properties #region Data short _attributeId = -1; #if !PBTCOMPILER public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0} attr({1}) staticResourceId({2})", RecordType, AttributeId, StaticResourceId); } #endif #endregion Data } // Text content between the begin and end tag of an element. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlTextRecord : BamlStringValueRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.Text; } } #endregion Properties } // This is a text record within a [Static/Dynamic]ResourceExtension. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlTextWithIdRecord : BamlTextRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { ValueId = bamlBinaryReader.ReadInt16(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(ValueId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlTextWithIdRecord newRecord = (BamlTextWithIdRecord)record; newRecord._valueId = _valueId; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.TextWithId; } } internal Int16 ValueId { get { return _valueId; } set { _valueId = value; } } #endregion Properties #region Data Int16 _valueId; #endregion Data } // Text content between the begin and end tag of an element that will be parsed using a type converter. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlTextWithConverterRecord : BamlTextRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { base.LoadRecordData(bamlBinaryReader); ConverterTypeId = bamlBinaryReader.ReadInt16(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { base.WriteRecordData(bamlBinaryWriter); bamlBinaryWriter.Write(ConverterTypeId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlTextWithConverterRecord newRecord = (BamlTextWithConverterRecord)record; newRecord._converterTypeId = _converterTypeId; } #endif #endregion Methods #region Properties // The following are stored in the baml stream // ID of this type converter. Referenced in other baml records where a // Type is needed. internal short ConverterTypeId { get { return _converterTypeId; } set { _converterTypeId = value; } } // Additional properties not stored in the baml stream internal override BamlRecordType RecordType { get { return BamlRecordType.TextWithConverter; } } #endregion Properties #region Data short _converterTypeId = 0; #endregion Data } // Marks the start of a Baml document. This must always be the first // record in a BAML stream. It contains version information, and other // document wide directives. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlDocumentStartRecord : BamlRecord { #region Methods // Writes data at the current position. The seek pointer points // to byte after the end of record when done. internal override void Write(BinaryWriter bamlBinaryWriter) { // Remember the file location of this baml record. This // is needed if we have to come back later to update the [....] mode. if (FilePos == -1 && bamlBinaryWriter != null) { FilePos = bamlBinaryWriter.Seek(0,SeekOrigin.Current); } base.Write(bamlBinaryWriter); } // Adjust seeks pointer to this Record and updates the data. // Then sets seek pointer pack to original. // NOTE: This will ONLY work for file sizes under 2 gig. This is // not a problem for current useage, since this is mostly used // when updating LoadAsync attribute on the DocumentStart record, // which is usually set on the first element in the xaml file. internal virtual void UpdateWrite(BinaryWriter bamlBinaryWriter) { // default implementation, class should override if // wants to optimize to only update dirty data. long currentPosiition = bamlBinaryWriter.Seek(0,SeekOrigin.Current); // seek to original record position. Debug.Assert(FilePos != -1,"UpdateWrite called but Write Never was"); // Note: This only works for files up to 2 gig in length. // This is not a new restriction, but it should be // fixed to work with larger files... bamlBinaryWriter.Seek((int)FilePos,SeekOrigin.Begin); Write(bamlBinaryWriter); bamlBinaryWriter.Seek( (int) currentPosiition,SeekOrigin.Begin); } #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { LoadAsync = bamlBinaryReader.ReadBoolean(); MaxAsyncRecords = bamlBinaryReader.ReadInt32(); DebugBaml = bamlBinaryReader.ReadBoolean(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(LoadAsync); bamlBinaryWriter.Write(MaxAsyncRecords); bamlBinaryWriter.Write(DebugBaml); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlDocumentStartRecord newRecord = (BamlDocumentStartRecord)record; newRecord._maxAsyncRecords = _maxAsyncRecords; newRecord._loadAsync = _loadAsync; newRecord._filePos = _filePos; newRecord._debugBaml = _debugBaml; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.DocumentStart; } } internal bool LoadAsync { get { return _loadAsync; } #if !PBTCOMPILER set { _loadAsync = value; } #endif } internal int MaxAsyncRecords { get { return _maxAsyncRecords; } set { _maxAsyncRecords = value; } } // Position in the baml file stream internal long FilePos { get { return _filePos; } set { _filePos = value; } } // Are there Debug Baml Records in this Baml Stream internal bool DebugBaml { get { return _debugBaml; } set { _debugBaml = value; } } #endregion Properties #region Data int _maxAsyncRecords = -1; bool _loadAsync = false; long _filePos = -1; bool _debugBaml = false; #endregion Data } // This marks the end tag of an element //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlElementEndRecord : BamlRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.ElementEnd; } } #endregion Properties } // This marks the start tag of an element being used as the key for an IDictionary internal class BamlKeyElementStartRecord : BamlDefAttributeKeyTypeRecord, IBamlDictionaryKey { internal BamlKeyElementStartRecord() { Pin(); // Don't allow this record to be recycled in the read cache. } #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.KeyElementStart; } } #endregion Properties } // This marks the end tag of an element being used as the key for an IDictionary internal class BamlKeyElementEndRecord : BamlElementEndRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.KeyElementEnd; } } #endregion Properties } // This marks the end of the baml stream, or document. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlDocumentEndRecord : BamlRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.DocumentEnd; } } #endregion Properties } // The following records are used internally in the baml stream to // define attribute (eg - property), type and assembly information // for records that follow later on in the stream. They are never // publically exposed // Information about an assembly where a type is defined //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlAssemblyInfoRecord : BamlVariableSizedRecord { internal BamlAssemblyInfoRecord() { Pin(); // Don't allow this record to be recycled in the read cache. AssemblyId = -1; } #region Methods #if !PBTCOMPILER // LoadRecord specific data internal override void LoadRecordData(BinaryReader bamlBinaryReader) { AssemblyId = bamlBinaryReader.ReadInt16(); AssemblyFullName = bamlBinaryReader.ReadString(); } #endif // write record specific Data. internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { // write out an int for record size but we'll go back and fill bamlBinaryWriter.Write(AssemblyId); bamlBinaryWriter.Write(AssemblyFullName); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlAssemblyInfoRecord newRecord = (BamlAssemblyInfoRecord)record; newRecord._assemblyFullName = _assemblyFullName; newRecord._assembly = _assembly; } #endif #endregion Methods #region Properties // The following are stored in the baml stream // ID of this assembly internal short AssemblyId { get { short value = (short) _flags[_assemblyIdLowSection]; value |= (short) (_flags[_assemblyIdHighSection] << 8); return value; } set { _flags[_assemblyIdLowSection] = (short) (value & 0xff); _flags[_assemblyIdHighSection] = (short) ((value & 0xff00) >> 8); } } // Allocate space in _flags. // BitVector32 doesn't support 16 bit sections, so we have to break // it up into 2 sections. private static BitVector32.Section _assemblyIdLowSection = BitVector32.CreateSection( (short)0xff, BamlVariableSizedRecord.LastFlagsSection ); private static BitVector32.Section _assemblyIdHighSection = BitVector32.CreateSection( (short)0xff, _assemblyIdLowSection ); #if !PBTCOMPILER // This provides subclasses with a referece section to create their own section. internal new static BitVector32.Section LastFlagsSection { get { return _assemblyIdHighSection; } } #endif // Full name of this assembly, excluding any suffix. This has // the format "AssemblyName, Version, Culture, PublicKeyToken" when we // have a true full name. Sometimes we aren't given the full assembly // name, in which case the full name is the same as the short name. internal string AssemblyFullName { get { return _assemblyFullName; } set { _assemblyFullName = value; } } // The following are not part of the BAML stream // Identify type of record internal override BamlRecordType RecordType { get { return BamlRecordType.AssemblyInfo; } } // The actual loaded assembly internal Assembly Assembly { get { return _assembly; } set { _assembly = value; } } #endregion Properties #region Data string _assemblyFullName; Assembly _assembly; #endregion Data } // Information about a type for an element, object or property //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlTypeInfoRecord : BamlVariableSizedRecord { internal BamlTypeInfoRecord() { Pin(); // Don't allow this record to be recycled in the read cache. TypeId = -1; } #region Methods #if !PBTCOMPILER // LoadRecord specific data internal override void LoadRecordData(BinaryReader bamlBinaryReader) { TypeId = bamlBinaryReader.ReadInt16(); AssemblyId = bamlBinaryReader.ReadInt16(); TypeFullName = bamlBinaryReader.ReadString(); // Note that the upper 4 bits of the AssemblyId are used for flags _typeInfoFlags = (TypeInfoFlags)(AssemblyId >> 12); _assemblyId &= 0x0FFF; } #endif // write record specific Data. internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { // write out an int for record size but we'll go back and fill bamlBinaryWriter.Write(TypeId); // Note that the upper 4 bits of the AssemblyId are used for flags bamlBinaryWriter.Write((short)(((ushort)AssemblyId) | (((ushort)_typeInfoFlags) << 12))); bamlBinaryWriter.Write(TypeFullName); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlTypeInfoRecord newRecord = (BamlTypeInfoRecord)record; newRecord._typeInfoFlags = _typeInfoFlags; newRecord._assemblyId = _assemblyId; newRecord._typeFullName = _typeFullName; newRecord._type = _type; } #endif #endregion Methods #region Properties // The following are stored in the baml stream // ID of this type. Refenced in other baml records where a // Type is needed. internal short TypeId { get { short value = (short) _flags[_typeIdLowSection]; value |= (short) (_flags[_typeIdHighSection] << 8); return value; } set { _flags[_typeIdLowSection] = (short) (value & 0xff); _flags[_typeIdHighSection] = (short) ((value & 0xff00) >> 8); } } // Assembly id of the assembly where this type is defined. // NOTE: This is always positive in BAML files, but can be set // to -1 for known types when created programmatically. internal short AssemblyId { get { return _assemblyId; } set { // Make sure we don't intrude on the Flags portion of the assembly ID if (_assemblyId > 0x0FFF) { throw new XamlParseException(SR.Get(SRID.ParserTooManyAssemblies)); } _assemblyId = value; } } // Fully qualified name of type, including namespace internal string TypeFullName { get { return _typeFullName; } set { _typeFullName = value; } } // Additional properties not stored in the baml stream internal override BamlRecordType RecordType { get { return BamlRecordType.TypeInfo; } } #if !PBTCOMPILER // Actual type. Filled in here when xaml is used to create // a tree, and the token reader knows the type internal Type Type { get { return _type; } set { _type = value; } } // Extract the namespace from the type full name and return // it. We are assuming here that the type full name has a single // classname at the end and we are not refering to a nested class... internal string ClrNamespace { get { int periodIndex = _typeFullName.LastIndexOf('.'); return periodIndex > 0 ? _typeFullName.Substring(0, periodIndex) : string.Empty; } } #endif // True if there is a serializer associated with this type internal virtual bool HasSerializer { get { return false; } } internal bool IsInternalType { #if !PBTCOMPILER get { return ((_typeInfoFlags & TypeInfoFlags.Internal) == TypeInfoFlags.Internal); } #endif set { // Don't allow resetting to false (i.e. converting back top public if // it becomes non-public, for added safety. if (value) { _typeInfoFlags |= TypeInfoFlags.Internal; } } } #endregion Properties #region Data // Allocate space in _flags. // BitVector32 doesn't support 16 bit sections, so we have to break // it up into 2 sections. private static BitVector32.Section _typeIdLowSection = BitVector32.CreateSection( (short)0xff, BamlVariableSizedRecord.LastFlagsSection ); private static BitVector32.Section _typeIdHighSection = BitVector32.CreateSection( (short)0xff, _typeIdLowSection ); #if !PBTCOMPILER // This provides subclasses with a referece section to create their own section. internal new static BitVector32.Section LastFlagsSection { get { return _typeIdHighSection; } } #endif // Flags contained in TypeInfo that give additional information // about the type that is determined at compile time. [Flags] private enum TypeInfoFlags : byte { Internal = 0x1, UnusedTwo = 0x2, UnusedThree = 0x4, } TypeInfoFlags _typeInfoFlags = 0; short _assemblyId = -1; string _typeFullName; #if !PBTCOMPILER Type _type; #endif #endregion Data } // Type info record for a type that has a custom serializer associated with it. // This gives the serializer type that will be used when deserializing this type //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlTypeInfoWithSerializerRecord : BamlTypeInfoRecord { internal BamlTypeInfoWithSerializerRecord() { Pin(); // Don't allow this record to be recycled in the read cache. } #region Methods #if !PBTCOMPILER // LoadRecord specific data internal override void LoadRecordData(BinaryReader bamlBinaryReader) { base.LoadRecordData(bamlBinaryReader); SerializerTypeId = bamlBinaryReader.ReadInt16(); } #endif // write record specific Data. internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { base.WriteRecordData(bamlBinaryWriter); bamlBinaryWriter.Write(SerializerTypeId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlTypeInfoWithSerializerRecord newRecord = (BamlTypeInfoWithSerializerRecord)record; newRecord._serializerTypeId = _serializerTypeId; newRecord._serializerType = _serializerType; } #endif #endregion Methods #region Properties // The following are stored in the baml stream // ID of this type. Refenced in other baml records where a // Type is needed. internal short SerializerTypeId { get { return _serializerTypeId; } set { _serializerTypeId = value; } } // Additional properties not stored in the baml stream internal override BamlRecordType RecordType { get { return BamlRecordType.TypeSerializerInfo; } } #if !PBTCOMPILER // Actual type of associated serializer. Filled in here when xaml is used to create // a tree, and the token reader knows the type of the serializer, or // when we are reading the baml file and have determined the // serializer type. internal Type SerializerType { get { return _serializerType; } set { _serializerType = value; } } #endif // True if there is a serializer associated with this type. A serializer // will never be the first type object in a baml file, so its type ID will // never be 0. Any other ID indicates we have a serializer. internal override bool HasSerializer { get { Debug.Assert( SerializerTypeId != 0 ); return true; } } #endregion Properties #region Data short _serializerTypeId = 0; #if !PBTCOMPILER Type _serializerType; #endif #endregion Data } // Used for mapping properties and events to an owner type, given the // name of the attribute. Note that Attribute is used for historical // reasons and for similarities to Xml attributes. For us attributes // are just properties and events. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlAttributeInfoRecord : BamlVariableSizedRecord { internal BamlAttributeInfoRecord() { Pin(); // Don't allow this record to be recycled in the read cache. AttributeUsage = BamlAttributeUsage.Default; } #region Methods #if !PBTCOMPILER // LoadRecord specific data internal override void LoadRecordData(BinaryReader bamlBinaryReader) { AttributeId = bamlBinaryReader.ReadInt16(); OwnerTypeId = bamlBinaryReader.ReadInt16(); AttributeUsage = (BamlAttributeUsage)bamlBinaryReader.ReadByte(); Name = bamlBinaryReader.ReadString(); } #endif // write record specific Data. internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { // write out an int for record size but we'll go back and fill bamlBinaryWriter.Write(AttributeId); bamlBinaryWriter.Write(OwnerTypeId); bamlBinaryWriter.Write((Byte)AttributeUsage); bamlBinaryWriter.Write(Name); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlAttributeInfoRecord newRecord = (BamlAttributeInfoRecord)record; newRecord._ownerId = _ownerId; newRecord._attributeId = _attributeId; newRecord._name = _name; newRecord._ownerType = _ownerType; newRecord._Event = _Event; newRecord._dp = _dp; newRecord._ei = _ei; newRecord._pi = _pi; newRecord._smi = _smi; newRecord._gmi = _gmi; newRecord._dpOrMiOrPi = _dpOrMiOrPi; } #endif #endregion Methods #region Properties // The following 3 properties are stored in the Baml file and are read and // written by the BamlRecordReader and BamlXamlNodeWriter internal short OwnerTypeId { get { return _ownerId; } set { _ownerId = value; } } internal short AttributeId { set { _attributeId = value; } get { return _attributeId; } } internal string Name { get { return _name; } set { _name = value; } } // The following properties are derived at runtime from the above 3 properties using // the Mapper. Which are set depends on the attribute and the context in which it is // used. internal override BamlRecordType RecordType { get { return BamlRecordType.AttributeInfo; } } #if !PBTCOMPILER // Return type of property. Note that this uses the same logic as // Mapper.GetPropertyType but uses the cached values of DP, PropInfo // and AttachedPropertySetter. internal Type GetPropertyType() { Type validType = null; DependencyProperty dp = DP; if (dp == null) { MethodInfo methodInfo = AttachedPropertySetter; if (methodInfo == null) { PropertyInfo propInfo = PropInfo; validType = propInfo.PropertyType; } else { ParameterInfo[] paramInfo = methodInfo.GetParameters(); validType = paramInfo[1].ParameterType; } } else { validType = dp.PropertyType; } return validType; } #endif ////// Set the PropertyMember, which can is assumed to be a MethodInfo for /// the static setter method for a DP or a PropertyInfo for the clr property /// ////// The possibility of having multiple member info cached for an attribute is when a /// dependency property that does not belong to the default namespace is used in once /// in a once with a namespace prefix and once without it. When it has a namespace /// prefix we correctly find the dependency property for it. However when it does not /// have a namespace prefix it the parser tries to look it up in the default namespace /// and falls back to using the clr wrapper's property info for it instead. Another /// scenario that requires caching more than one property info is when a dependency /// property has both a static settor and a clr wrapper. /// internal void SetPropertyMember (object propertyMember) { Debug.Assert((propertyMember is MethodInfo) || (propertyMember is PropertyInfo) || (KnownTypes.Types[(int)KnownElements.DependencyProperty].IsAssignableFrom(propertyMember.GetType())), "Cache can hold either a MethodInfo and/or a PropertyInfo and/or a DependencyProperty for a given attribute"); if (PropertyMember == null) { PropertyMember = propertyMember; } else { // Cache a additional MemberInfo for the given attribute object[] arr = PropertyMember as object[]; if (arr == null) { arr = new object[3]; arr[0] = PropertyMember; arr[1] = propertyMember; } else { Debug.Assert(arr.Length == 3 && arr[0] != null && arr[1] != null); arr[2] = propertyMember; } } } ////// Return the PropertyMember, which can is assumed to be a MethodInfo for /// the static setter method for a DP or a PropertyInfo for the clr property /// ////// The possibility of having multiple member info cached for an attribute is when a /// dependency property that does not belong to the default namespace is used in once /// in a once with a namespace prefix and once without it. When it has a namespace /// prefix we correctly find the dependency property for it. However when it does not /// have a namespace prefix it the parser tries to look it up in the default namespace /// and falls back to using the clr wrapper's property info for it instead. Another /// scenario that requires caching more than one property info is when a dependency /// property has both a static settor and a clr wrapper. /// internal object GetPropertyMember(bool onlyPropInfo) { if (PropertyMember == null || PropertyMember is MemberInfo || KnownTypes.Types[(int)KnownElements.DependencyProperty].IsAssignableFrom(PropertyMember.GetType( )) ) { if (onlyPropInfo) { #if PBTCOMPILER return PropertyMember as PropertyInfo; #else return PropInfo; #endif } else { return PropertyMember; } } else { // The attribute has multiple member info. Choose which one to return. object[] arr = (object[])PropertyMember; Debug.Assert(arr.Length == 3 && arr[0] != null && arr[1] != null); // If someone queries any MemberInfo for the given attribute then we return the // first member info cached for it. If they are looking specifically for a // PropertyInfo we try and find them one. if (onlyPropInfo) { if (arr[0] is PropertyInfo) { return (PropertyInfo)arr[0]; } else if (arr[1] is PropertyInfo) { return (PropertyInfo)arr[1]; } else { return arr[2] as PropertyInfo; } } else { return arr[0]; } } } // Cached value of the DependencyProperty, MethodInfo for the static setter // method, or the PropertyInfo for a given property. If this is an // event, then this is null. internal object PropertyMember { get { return _dpOrMiOrPi; } set { _dpOrMiOrPi = value; } } #if !PBTCOMPILER // The cached type of the owner or declarer of this property internal Type OwnerType { get { return _ownerType; } set { _ownerType = value; } } // Cached value of the routed event id, if this attribute is for a // routed event. If not a routed event, this is null. internal RoutedEvent Event { get { return _Event; } set { _Event = value; } } // Cached value of DP, if available internal DependencyProperty DP { get { if (null != _dp) return _dp; else return _dpOrMiOrPi as DependencyProperty; } set { _dp = value; if (_dp != null) { // Release the other copy of the string _name = _dp.Name; } } } // Cached value of static property setter method info, if available internal MethodInfo AttachedPropertySetter { get { return _smi; } set { _smi = value; } } // Cached value of static property getter method info, if available internal MethodInfo AttachedPropertyGetter { get { return _gmi; } set { _gmi = value; } } // Cached value of EventInfo, if available internal EventInfo EventInfo { get { return _ei; } set { _ei = value; } } // Cached value of PropertyInfo, if available internal PropertyInfo PropInfo { get { return _pi; } set { _pi = value; } } internal bool IsInternal { get { return _flags[_isInternalSection] == 1 ? true : false; } set { _flags[_isInternalSection] = value ? 1 : 0; } } #endif // Some attributes have special usage, such as setting the XmlLang and XmlSpace // strings in the parser context. This is flagged with this property internal BamlAttributeUsage AttributeUsage { get { return (BamlAttributeUsage) _flags[_attributeUsageSection]; } set { _flags[_attributeUsageSection] = (int) value; } } // Allocate space in _flags. private static BitVector32.Section _isInternalSection = BitVector32.CreateSection( 1, BamlVariableSizedRecord.LastFlagsSection ); private static BitVector32.Section _attributeUsageSection = BitVector32.CreateSection( 3, _isInternalSection ); #if !PBTCOMPILER // This provides subclasses with a referece section to create their own section. internal new static BitVector32.Section LastFlagsSection { get { return _attributeUsageSection; } } #endif #endregion Properties #if !PBTCOMPILER public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0} owner={1} attr({2}) is '{3}'", RecordType, GetTypeName(OwnerTypeId), AttributeId, _name); } #endif #region Data short _ownerId; short _attributeId; string _name; #if !PBTCOMPILER Type _ownerType = null; RoutedEvent _Event = null; DependencyProperty _dp = null; EventInfo _ei = null; PropertyInfo _pi = null; MethodInfo _smi = null; MethodInfo _gmi = null; #endif object _dpOrMiOrPi = null; // MethodInfo, PropertyInfo or DependencyProperty #endregion Data } // Information about a String that is an entry in the String table. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlStringInfoRecord : BamlVariableSizedRecord { internal BamlStringInfoRecord() { Pin(); // Don't allow this record to be recycled in the read cache. StringId = -1; } #region Methods #if !PBTCOMPILER // LoadRecord specific data internal override void LoadRecordData(BinaryReader bamlBinaryReader) { StringId = bamlBinaryReader.ReadInt16(); Value = bamlBinaryReader.ReadString(); } #endif // write record specific Data. internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { // write out an int for string Id bamlBinaryWriter.Write(StringId); bamlBinaryWriter.Write(Value); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlStringInfoRecord newRecord = (BamlStringInfoRecord)record; newRecord._value = _value; } #endif #endregion Methods #region Properties // Resource Identifier pointing to the StringTable Entry internal short StringId { get { short value = (short) _flags[_stringIdLowSection]; value |= (short) (_flags[_stringIdHighSection] << 8); return value; } set { _flags[_stringIdLowSection] = (short) (value & 0xff); _flags[_stringIdHighSection] = (short) ((value & 0xff00) >> 8); } } // Resource String internal string Value { get { return _value; } set { _value = value; } } // Additional properties not stored in the baml stream internal override BamlRecordType RecordType { get { return BamlRecordType.StringInfo; } } // True if there is a serializer associated with this type internal virtual bool HasSerializer { get { return false; } } #endregion Properties #if !PBTCOMPILER public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0} stringId({1}='{2}'", RecordType, StringId, _value); } #endif #region Data // Allocate space in _flags. // BitVector32 doesn't support 16 bit sections, so we have to break // it up into 2 sections. private static BitVector32.Section _stringIdLowSection = BitVector32.CreateSection( (short)0xff, BamlVariableSizedRecord.LastFlagsSection ); private static BitVector32.Section _stringIdHighSection = BitVector32.CreateSection( (short)0xff, _stringIdLowSection ); #if !PBTCOMPILER // This provides subclasses with a referece section to create their own section. internal new static BitVector32.Section LastFlagsSection { get { return _stringIdHighSection; } } #endif string _value ; #endregion Data } // Sets the content property context for an element //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlContentPropertyRecord : BamlRecord { #region Methods #if !PBTCOMPILER // LoadRecord specific data internal override void LoadRecordData(BinaryReader bamlBinaryReader) { AttributeId = bamlBinaryReader.ReadInt16(); } #endif // write record specific Data. internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { // write out an int for attribute Id bamlBinaryWriter.Write(AttributeId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlContentPropertyRecord newRecord = (BamlContentPropertyRecord)record; newRecord._attributeId = _attributeId; } #endif #endregion Methods #region Properties // Id of the property being set as the context internal short AttributeId { get { return _attributeId; } set { _attributeId = value; } } // Additional properties not stored in the baml stream internal override BamlRecordType RecordType { get { return BamlRecordType.ContentProperty; } } // True if there is a serializer associated with this type internal virtual bool HasSerializer { get { return false; } } #endregion Properties #region Data short _attributeId = -1; #endregion Data } // Debugging Linenumber record. Linenumber from the XAML //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlLineAndPositionRecord : BamlRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { LineNumber = (uint) bamlBinaryReader.ReadInt32(); LinePosition = (uint) bamlBinaryReader.ReadInt32(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(LineNumber); bamlBinaryWriter.Write(LinePosition); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlLineAndPositionRecord newRecord = (BamlLineAndPositionRecord)record; newRecord._lineNumber = _lineNumber; newRecord._linePosition = _linePosition; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.LineNumberAndPosition; } } // Id of the type of this object internal uint LineNumber { get { return _lineNumber; } set { _lineNumber = value; } } internal uint LinePosition { get { return _linePosition; } set { _linePosition = value; } } internal override Int32 RecordSize { get { return 8; } } uint _lineNumber; uint _linePosition; #endregion Properties #if !PBTCOMPILER public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0} LineNum={1} Pos={2}", RecordType, LineNumber, LinePosition); } #endif } // Debugging Line Position record. Line Position from the XAML //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlLinePositionRecord : BamlRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { LinePosition = (uint) bamlBinaryReader.ReadInt32(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(LinePosition); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlLinePositionRecord newRecord = (BamlLinePositionRecord)record; newRecord._linePosition = _linePosition; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.LinePosition; } } internal uint LinePosition { get { return _linePosition; } set { _linePosition = value; } } internal override Int32 RecordSize { get { return 4; } } uint _linePosition; #endregion Properties #if !PBTCOMPILER public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0} LinePos={1}", RecordType, LinePosition); } #endif } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. /****************************************************************************\ * * File: BamlRecords.cs * * Purpose: Contains implementation for specific BamlRecords * * History: * 6/06/01: rogerg Created * 5/28/03: peterost Ported to wcp * 10/6/03: peterost Reorganized to remove DP - clr distinction * * Copyright (C) 2002 by Microsoft Corporation. All rights reserved. * \***************************************************************************/ using System; using System.Xml; using System.IO; using System.Text; using System.Collections.Generic; using System.Collections; using System.Globalization; using System.ComponentModel; using System.Security.Permissions; using System.Diagnostics; using System.Reflection; using System.Collections.Specialized; using MS.Internal.IO.Packaging.CompoundFile; #if PBTCOMPILER using TCH = MS.Internal.Markup.TypeConverterHelper; #else using System.Windows; using System.Windows.Media; using System.Windows.Threading; using MS.Internal.PresentationFramework; // SafeSecurityHelper using TCH = System.Windows.Markup.TypeConverterHelper; #endif using System.Runtime.InteropServices; using MS.Utility; using MS.Internal; // Disabling 1634 and 1691: // In order to avoid generating warnings about unknown message numbers and // unknown pragmas when compiling C# source code with the C# compiler, // you need to disable warnings 1634 and 1691. (Presharp Documentation) #pragma warning disable 1634, 1691 #if PBTCOMPILER namespace MS.Internal.Markup #else namespace System.Windows.Markup #endif { // Types of records. Note that this is a superset of XamlNodeTypes internal enum BamlRecordType : byte { ////// Unknown Node /// // !!BamlRecordManager class relies on Unknown = 0 for initialization Unknown = 0, ////// Start Document Node /// DocumentStart, // 1 ////// End Document Node /// DocumentEnd, // 2 ////// Start Element Node, which may be a CLR object or a DependencyObject /// ElementStart, // 3 ////// End Element Node /// ElementEnd, // 4 ////// Property Node, which may be a CLR property or a DependencyProperty /// Property, // 5 ////// Binary serialization of a property /// PropertyCustom, // 6 ////// Complex Property Node /// PropertyComplexStart, // 7 ////// End Complex Property Node /// PropertyComplexEnd, // 8 ////// Start Array Property Node /// PropertyArrayStart, // 9 ////// End Array Property Node /// PropertyArrayEnd, // 10 ////// Star IList Property Node /// PropertyIListStart, // 11 ////// End PropertyIListStart Node /// PropertyIListEnd, // 12 ////// Start IDictionary Property Node /// PropertyIDictionaryStart, // 13 ////// End IDictionary Property Node /// PropertyIDictionaryEnd, // 14 ////// LiteralContent Node /// LiteralContent, // 15 ////// Text Node /// Text, // 16 ////// Text that has an associated custom typeconverter /// TextWithConverter, // 17 ////// RoutedEventNode /// RoutedEvent, // 18 ////// ClrEvent Node /// ClrEvent, // 19 ////// XmlnsProperty Node /// XmlnsProperty, // 20 ////// XmlAttribute Node /// XmlAttribute, // 21 ////// Processing Intstruction Node /// ProcessingInstruction, // 22 ////// Comment Node /// Comment, // 23 ////// DefTag Node /// DefTag, // 24 ////// x:name="value" attribute. One typical use of this /// attribute is to define a key to use when inserting an item into an IDictionary /// DefAttribute, // 25 ////// EndAttributes Node /// EndAttributes, // 26 ////// PI xml - clr namespace mapping /// PIMapping, // 27 ////// Assembly information /// AssemblyInfo, // 28 ////// Type information /// TypeInfo, // 29 ////// Type information for a Type that has an associated custom serializer /// TypeSerializerInfo, // 30 ////// Attribute (eg - properties and events) information /// AttributeInfo, // 31 ////// Resource information /// StringInfo, // 32 ////// Property Resource Reference /// PropertyStringReference, // 33 ////// Record for setting a property to a Type reference. This is used for /// properties that are of type "Type" /// PropertyTypeReference, // 34 ////// Property that has a simple MarkupExtension value. /// PropertyWithExtension, // 35 ////// Property that has an associated custom typeconverter /// PropertyWithConverter, // 36 ////// Start a deferable content block /// DeferableContentStart, // 37 ////// x:name="value" attribute when used within a defer load /// dictionary. These keys are hoisted to the front of the dictionary when /// written to baml. /// DefAttributeKeyString, // 38 ////// Implied key that is a Type attribute when used within a defer load /// dictionary. These keys are hoisted to the front of the dictionary when /// written to baml. /// DefAttributeKeyType, // 39 ////// This marks the start of an element tree that is used as the key in /// an IDictionary. /// KeyElementStart, // 40 ////// This marks the end of an element tree that is used as the key in /// an IDictionary. /// KeyElementEnd, // 41 ////// Record marks the start of a section containing constructor parameters /// ConstructorParametersStart, // 42 ////// Record marks the end of a section containing constructor parameters /// ConstructorParametersEnd, // 43 ////// Constructor parameter that has been resolved to a Type. /// ConstructorParameterType, // 44 ////// Record that has info about which event or id to connect to in an object tree. /// ConnectionId, // 45 ////// Record that set the conntent property context for the element /// ContentProperty, // 46 ////// ElementStartRecord that also carries an element name. /// NamedElementStart, // 47 ////// Start of StaticResourceExtension within the header of a deferred section. /// StaticResourceStart, // 48 ////// End of a StaticResourceExtension within the header of a deferred section. /// StaticResourceEnd, // 49 ////// BamlRecord that carries an identifier for a StaticResourceExtension /// within the header of a deferred section. /// StaticResourceId, // 50 ////// This is a TextRecord that holds an Id for the String value it represents. /// TextWithId, // 51 ////// PresentationOptions:Freeze="value" attribute. Used for ignorable /// WPF-specific parsing options /// PresentationOptionsAttribute, // 52 ////// Debugging information record that holds the source XAML linenumber. /// LineNumberAndPosition, // 53 ////// Debugging information record that holds the source XAML line position. /// LinePosition, // 54 ////// OptimizedStaticResourceExtension within the header of a deferred section. /// OptimizedStaticResource, // 55 ////// BamlPropertyRecord that carries an identifier for a StaticResourceExtension /// within the header of a deferred section. /// PropertyWithStaticResourceId, // 56 ////// Placeholder to mark last record /// LastRecordType } ////// Some attributes have special usages or cause additional actions when they /// are set on an element. This can be have some other effects /// such as setting the xml:lang or xml:space values in the parser context. /// The PropertyUsage describes addition effects or usage for this property. /// internal enum BamlAttributeUsage : short { ///A regular property that has no other use Default = 0, ///A property that has xml:lang information XmlLang, ///A property that has xml:space information XmlSpace, ///A property that has the RuntimeIdProperty information RuntimeName, } // This class handles allocation, read and write management of baml records. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlRecordManager { #if !PBTCOMPILER // Genericaly load and create the proper class. // This method assumes the seek pointer has already moved passed the recordType // field and is at the RecordSize or record contents (depending on record). // This method is used so the caller can first read the type of record, and expects // to get back the entire record, or nothing (for async support). internal BamlRecord ReadNextRecord( BinaryReader bamlBinaryReader, long bytesAvailable, BamlRecordType recordType) { BamlRecord bamlRecord; // = null // Create the proper BamlRecord based on the recordType. The assembly, // type and attribute records are created every time, since they are // used by the BamlMapTable. The other records are re-used, so they // are created once and cached. switch(recordType) { case BamlRecordType.AssemblyInfo: bamlRecord = new BamlAssemblyInfoRecord(); break; case BamlRecordType.TypeInfo: bamlRecord = new BamlTypeInfoRecord(); break; case BamlRecordType.TypeSerializerInfo: bamlRecord = new BamlTypeInfoWithSerializerRecord(); break; case BamlRecordType.AttributeInfo: bamlRecord = new BamlAttributeInfoRecord(); break; case BamlRecordType.StringInfo: bamlRecord = new BamlStringInfoRecord(); break; case BamlRecordType.DefAttributeKeyString: bamlRecord = new BamlDefAttributeKeyStringRecord(); break; case BamlRecordType.DefAttributeKeyType: bamlRecord = new BamlDefAttributeKeyTypeRecord(); break; case BamlRecordType.KeyElementStart: bamlRecord = new BamlKeyElementStartRecord(); break; default: // Get the current record from the cache. If there's nothing there yet, // or if what is there is pinned, then create one. Note that records in the // read cache are implicitly recycled, and records in the write cache are explicitly // recycled (i.e., there's a ReleaseWriteRecord, but no ReleaseReadRecord). bamlRecord = _readCache[(int)recordType]; if (null == bamlRecord || bamlRecord.IsPinned ) { bamlRecord = _readCache[(int)recordType] = AllocateRecord(recordType); } break; } bamlRecord.Next = null; if (null != bamlRecord) { // If LoadRecordSize indicates it can determine the record size // and has determined that there is enough content to load the // entire record, then continue. if (bamlRecord.LoadRecordSize(bamlBinaryReader, bytesAvailable) && bytesAvailable >= bamlRecord.RecordSize) { bamlRecord.LoadRecordData(bamlBinaryReader); } else { bamlRecord = null; } } return bamlRecord; } ////// Return the object if it should be treated as IAddChild, otherwise return null /// static internal IAddChild AsIAddChild(object obj) { IAddChild iac = obj as IAddChildInternal; return iac; } #endif ////// True if type should be treated as IAddChild /// static internal bool TreatAsIAddChild(Type parentObjectType) { return (KnownTypes.Types[(int)KnownElements.IAddChildInternal].IsAssignableFrom( parentObjectType )); } static internal BamlRecordType GetPropertyStartRecordType(Type propertyType, bool propertyCanWrite) { BamlRecordType recordType; if (propertyType.IsArray) { recordType = BamlRecordType.PropertyArrayStart; } else if (typeof(IDictionary).IsAssignableFrom(propertyType)) { recordType = BamlRecordType.PropertyIDictionaryStart; } else if ((typeof(IList).IsAssignableFrom(propertyType) || BamlRecordManager.TreatAsIAddChild(propertyType) || (typeof(IEnumerable).IsAssignableFrom(propertyType) && !propertyCanWrite))) { // we're a list if: // 1) the property type is an IList. // 2) the property type is an IAddChild (internal). // 3) the property type is an IEnumerable and read-only and the parent is an IAddChild (internal). // for the third case, we can't check the parent until run-time. recordType = BamlRecordType.PropertyIListStart; } else { recordType = BamlRecordType.PropertyComplexStart; } return recordType; } #if !PBTCOMPILER internal BamlRecord CloneRecord(BamlRecord record) { BamlRecord newRecord; switch (record.RecordType) { case BamlRecordType.ElementStart: if (record is BamlNamedElementStartRecord) { newRecord= new BamlNamedElementStartRecord(); } else { newRecord = new BamlElementStartRecord(); } break; case BamlRecordType.PropertyCustom: if (record is BamlPropertyCustomWriteInfoRecord) { newRecord = new BamlPropertyCustomWriteInfoRecord(); } else { newRecord = new BamlPropertyCustomRecord(); } break; default: newRecord = AllocateRecord(record.RecordType); break; } record.Copy(newRecord); return newRecord; } #endif // Helper function to create a BamlRecord from a BamlRecordType private BamlRecord AllocateWriteRecord(BamlRecordType recordType) { BamlRecord record; switch (recordType) { case BamlRecordType.PropertyCustom: record = new BamlPropertyCustomWriteInfoRecord(); break; default: record = AllocateRecord(recordType); break; } return record; } // Helper function to create a BamlRecord from a BamlRecordType private BamlRecord AllocateRecord(BamlRecordType recordType) { BamlRecord record; switch(recordType) { case BamlRecordType.DocumentStart: record = new BamlDocumentStartRecord(); break; case BamlRecordType.DocumentEnd: record = new BamlDocumentEndRecord(); break; case BamlRecordType.ConnectionId: record = new BamlConnectionIdRecord(); break; case BamlRecordType.ElementStart: record = new BamlElementStartRecord(); break; case BamlRecordType.ElementEnd: record = new BamlElementEndRecord(); break; case BamlRecordType.DeferableContentStart: record = new BamlDeferableContentStartRecord(); break; case BamlRecordType.DefAttributeKeyString: record = new BamlDefAttributeKeyStringRecord(); break; case BamlRecordType.DefAttributeKeyType: record = new BamlDefAttributeKeyTypeRecord(); break; case BamlRecordType.LiteralContent: record = new BamlLiteralContentRecord(); break; case BamlRecordType.Property: record = new BamlPropertyRecord(); break; case BamlRecordType.PropertyWithConverter: record = new BamlPropertyWithConverterRecord(); break; case BamlRecordType.PropertyStringReference: record = new BamlPropertyStringReferenceRecord(); break; case BamlRecordType.PropertyTypeReference: record = new BamlPropertyTypeReferenceRecord(); break; case BamlRecordType.PropertyWithExtension: record = new BamlPropertyWithExtensionRecord(); break; case BamlRecordType.PropertyCustom: record = new BamlPropertyCustomRecord(); break; case BamlRecordType.PropertyComplexStart: record = new BamlPropertyComplexStartRecord(); break; case BamlRecordType.PropertyComplexEnd: record = new BamlPropertyComplexEndRecord(); break; case BamlRecordType.RoutedEvent: record = new BamlRoutedEventRecord(); break; case BamlRecordType.PropertyArrayStart: record = new BamlPropertyArrayStartRecord(); break; case BamlRecordType.PropertyArrayEnd: record = new BamlPropertyArrayEndRecord(); break; case BamlRecordType.PropertyIListStart: record = new BamlPropertyIListStartRecord(); break; case BamlRecordType.PropertyIListEnd: record = new BamlPropertyIListEndRecord(); break; case BamlRecordType.PropertyIDictionaryStart: record = new BamlPropertyIDictionaryStartRecord(); break; case BamlRecordType.PropertyIDictionaryEnd: record = new BamlPropertyIDictionaryEndRecord(); break; case BamlRecordType.Text: record = new BamlTextRecord(); break; case BamlRecordType.TextWithConverter: record = new BamlTextWithConverterRecord(); break; case BamlRecordType.TextWithId: record = new BamlTextWithIdRecord(); break; case BamlRecordType.XmlnsProperty: record = new BamlXmlnsPropertyRecord(); break; case BamlRecordType.PIMapping: record = new BamlPIMappingRecord(); break; case BamlRecordType.DefAttribute: record = new BamlDefAttributeRecord(); break; case BamlRecordType.PresentationOptionsAttribute: record = new BamlPresentationOptionsAttributeRecord(); break; case BamlRecordType.KeyElementStart: record = new BamlKeyElementStartRecord(); break; case BamlRecordType.KeyElementEnd: record = new BamlKeyElementEndRecord(); break; case BamlRecordType.ConstructorParametersStart: record = new BamlConstructorParametersStartRecord(); break; case BamlRecordType.ConstructorParametersEnd: record = new BamlConstructorParametersEndRecord(); break; case BamlRecordType.ConstructorParameterType: record = new BamlConstructorParameterTypeRecord(); break; case BamlRecordType.ContentProperty: record = new BamlContentPropertyRecord(); break; case BamlRecordType.AssemblyInfo: case BamlRecordType.TypeInfo: case BamlRecordType.TypeSerializerInfo: case BamlRecordType.AttributeInfo: case BamlRecordType.StringInfo: Debug.Assert(false,"Assembly, Type and Attribute records are not cached, so don't ask for one."); record = null; break; case BamlRecordType.StaticResourceStart: record = new BamlStaticResourceStartRecord(); break; case BamlRecordType.StaticResourceEnd: record = new BamlStaticResourceEndRecord(); break; case BamlRecordType.StaticResourceId: record = new BamlStaticResourceIdRecord(); break; case BamlRecordType.LineNumberAndPosition: record = new BamlLineAndPositionRecord(); break; case BamlRecordType.LinePosition: record = new BamlLinePositionRecord(); break; case BamlRecordType.OptimizedStaticResource: record = new BamlOptimizedStaticResourceRecord(); break; case BamlRecordType.PropertyWithStaticResourceId: record = new BamlPropertyWithStaticResourceIdRecord(); break; default: Debug.Assert(false,"Unknown RecordType"); record = null; break; } return record; } // This should only be called from BamlRecordWriter -- it gets a record from the record // cache that must be freed with ReleaseRecord before GetRecord is called again. internal BamlRecord GetWriteRecord(BamlRecordType recordType) { // Create the cache of records used in writing, on demand if( _writeCache == null ) { _writeCache = new BamlRecord[(int)BamlRecordType.LastRecordType]; } BamlRecord record = _writeCache[(int)recordType]; if (null == record) { record = AllocateWriteRecord(recordType); } else { _writeCache[(int)recordType] = null; } // It is important to set RecordSize for variable size records // to a negative number to indicate that it has not been set yet. // Fixed size records should ignore this set. record.RecordSize = -1; return record; } //+--------------------------------------------------------------------------------------------- // // ReleaseWriteRecord // // Frees a record originally claimed with GetWriteRecord. Note that records in the // read cache are implicitly recycled, and records in the write cache are explicitly // recycled (i.e., there's a ReleaseWriteRecord, but no ReleaseReadRecord). // //+--------------------------------------------------------------------------------------------- internal void ReleaseWriteRecord(BamlRecord record) { // Put the write record back into the cache, if we're allowed to recycle it. if( !record.IsPinned ) { Debug.Assert(null == _writeCache[(int)record.RecordType]); if (null != _writeCache[(int)record.RecordType]) { // This is really an internal error. throw new InvalidOperationException(SR.Get(SRID.ParserMultiBamls)); } _writeCache[(int)record.RecordType] = record; } } // Cache of BamlRecords, used during read, to avoid lots of records from being // created. If a record gets pinned (BamlRecord.IsPinned gets set), it is not re-used. #if !PBTCOMPILER BamlRecord[] _readCache = new BamlRecord[(int)BamlRecordType.LastRecordType]; #endif // Cache of BamlRecords, used during write, also to avoid lots of records // from being created. BamlRecord[] _writeCache = null; //new BamlRecord[(int)BamlRecordType.LastRecordType]; } // The base of all baml records. This gives a fixed size record that contains // line number information used for generating error messages. Note that the // line number information is not currently written out to the baml stream. internal abstract class BamlRecord { #region Methods #if !PBTCOMPILER // If there are enough bytes available, load the record size from the // binary reader. For fixed size records that derive from BamlRecord, // there is no size field in the baml file, so this always succeeds. internal virtual bool LoadRecordSize( BinaryReader bamlBinaryReader, long bytesAvailable) { return true; } // Load record data. This does not include the record type, or the // size field, which are loaded separately. If the subclass has no // specific data to load, then don't override this. internal virtual void LoadRecordData(BinaryReader bamlBinaryReader) { } #endif // Writes data at the current position seek pointer points // to byte after the end of record when done. internal virtual void Write(BinaryWriter bamlBinaryWriter) { // BamlRecords may be used without a stream, so if you attempt to write when there // isn't a writer, just ignore it. if (bamlBinaryWriter == null) { return; } // Baml records always start with record type bamlBinaryWriter.Write((byte) RecordType); // IMPORTANT: The RecordType is the last thing written before calling // WriteRecordData. Some records assume the record type is located // directly before the current stream location and may change it, so // don't change where the record type is written in the stream!!! // Paint is one example of a DP object that will seek back to change // the record type if it is unable to serialize itself. WriteRecordData(bamlBinaryWriter); } // Write contents of the record, excluding size (if any) and record type. // If the subclass has no specific data to write out, don't override this. internal virtual void WriteRecordData(BinaryWriter bamlBinaryWriter) { } #endregion Methods #region Properties // Actual size of the complete BamlRecord (excluding RecordType) in bytes. // Currently limited to 2 gigabytes. Default size is 0 bytes of data. // Subclasses must override if they have a different size. internal virtual Int32 RecordSize { get { return 0; } set { Debug.Assert (value == -1, "Setting fixed record to an invalid size"); } } // Identifies the type off BAML record. This is used when casting to // a BamlRecord subclass. All subclasses **MUST** override this. internal virtual BamlRecordType RecordType { get { Debug.Assert(false, "Must override RecordType"); return BamlRecordType.Unknown; } } #if !PBTCOMPILER // Next Record pointer - used in BamlObjectFactory internal BamlRecord Next { get { return _nextRecord; } set { _nextRecord = value ; } } #endif // The BamlRecorManager keeps a cache of baml records and tries to reuse them automatically. // To keep a record from being cached, it can be pinned. For correct pinning we keep a // pin count. To save working set, we only have two bits for the reference count. // So if the reference count reaches three the record becomes permanently pinned. internal bool IsPinned { get { return PinnedCount > 0; } } // (See comment on IsPinned.) internal int PinnedCount { get { return _flags[_pinnedFlagSection]; } set { Debug.Assert( value <= 3 && value >= 0 ); _flags[_pinnedFlagSection] = value; } } // (See comment on IsPinned.) internal void Pin() { if( PinnedCount < 3 ) { ++PinnedCount; } } #if !PBTCOMPILER // (See comment on IsPinned.) internal void Unpin() { if( PinnedCount < 3 ) { --PinnedCount; } } internal virtual void Copy(BamlRecord record) { record._flags = _flags; record._nextRecord = _nextRecord; } #endif #endregion Properties #region Data // Internal flags for efficient storage // NOTE: bits here are used by sub-classes also. // This BitVector32 field is shared by subclasses to save working set. Sharing flags like this // is easier in e.g. FrameworkElement, where the class hierarchy is linear, but can be bug-prone otherwise. To make the // code less fragile, each class abstractly provides it's last section to subclasses(LastFlagsSection), which they can // use in their call to CreateSection. internal BitVector32 _flags; // Allocate space in _flags. private static BitVector32.Section _pinnedFlagSection = BitVector32.CreateSection( 3 /* Allocates two bits to store values up to 3 */ ); // This provides subclasses with a referece section to create their own section. internal static BitVector32.Section LastFlagsSection { get { return _pinnedFlagSection; } } #if !PBTCOMPILER private BamlRecord _nextRecord = null; #endif // Size of the record type field in the baml file. internal const int RecordTypeFieldLength = 1; #if !PBTCOMPILER public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0}", RecordType); } protected static string GetTypeName(int typeId) { string typeName = typeId.ToString(CultureInfo.InvariantCulture); if(typeId < 0) { KnownElements elm = (KnownElements)(-typeId); typeName = elm.ToString(); } return typeName; } // This helper checks for records that indicate that you're out of // an element start, and into it's "content" (in the xml sense). // We have to infer this, because unlike Xml, Baml doesn't provide // an end-attributes record. internal static bool IsContentRecord( BamlRecordType bamlRecordType ) { return bamlRecordType == BamlRecordType.PropertyComplexStart || bamlRecordType == BamlRecordType.PropertyArrayStart || bamlRecordType == BamlRecordType.PropertyIListStart || bamlRecordType == BamlRecordType.PropertyIDictionaryStart || bamlRecordType == BamlRecordType.Text; } #endif #endregion Data } // An abstract base class for records that record their size as part of the // baml stream. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal abstract class BamlVariableSizedRecord : BamlRecord { #region Methods #if !PBTCOMPILER // If there are enough bytes available, load the record size from the // binary reader. The default action is to load the 4 byte size from // the reader, if there are at least 4 bytes available. internal override bool LoadRecordSize( BinaryReader bamlBinaryReader, long bytesAvailable) { int recordSize; bool loadedSize = LoadVariableRecordSize(bamlBinaryReader, bytesAvailable, out recordSize); if (loadedSize) { RecordSize = recordSize; } return loadedSize; } // If there are enough bytes available, load the record size from the // binary reader. The default action is to load the 4 byte size from // the reader, if there are at least 4 bytes available. internal static bool LoadVariableRecordSize( BinaryReader bamlBinaryReader, long bytesAvailable, out int recordSize) { if (bytesAvailable >= MaxRecordSizeFieldLength) { recordSize = ((BamlBinaryReader)bamlBinaryReader).Read7BitEncodedInt(); return true; } else { recordSize = -1; return false; } } #endif protected int ComputeSizeOfVariableLengthRecord(long start, long end) { int size = (Int32)(end - start); int sizeOfSize = BamlBinaryWriter.SizeOf7bitEncodedSize(size); sizeOfSize = BamlBinaryWriter.SizeOf7bitEncodedSize(sizeOfSize+size); return (sizeOfSize+size); } // Writes data at the current position seek pointer points // to byte after the end of record when done. internal override void Write(BinaryWriter bamlBinaryWriter) { // BamlRecords may be used without a stream, so if you attempt to write when there // isn't a writer, just ignore it. if (bamlBinaryWriter == null) { return; } // Baml records always start with record type bamlBinaryWriter.Write((byte) RecordType); // Remember the file location of this baml record. This // is needed if we have to come back later to update the [....] mode. // IMPORTANT: The RecordType is the last thing written before calling // WriteRecordData. Some records assume the record type is located // directly before the current stream location and may change it, so // don't change where the record type is written in the stream!!! // Paint is one example of a DP object that will seek back to change // the record type if it is unable to serialize itself. // Write just the data, this is just to measure the size. long startSeekPosition = bamlBinaryWriter.Seek(0,SeekOrigin.Current); WriteRecordData(bamlBinaryWriter); long endSeekPosition = bamlBinaryWriter.Seek(0,SeekOrigin.Current); Debug.Assert(RecordSize < 0); RecordSize = ComputeSizeOfVariableLengthRecord(startSeekPosition, endSeekPosition); // seek back to the begining, this time write the size, then the data. bamlBinaryWriter.Seek((int)startSeekPosition, SeekOrigin.Begin); WriteRecordSize(bamlBinaryWriter); WriteRecordData(bamlBinaryWriter); } // Write the size of this record. The default action is to write the 4 byte // size, which may be overwritten later once WriteRecordData has been called. internal void WriteRecordSize(BinaryWriter bamlBinaryWriter) { ((BamlBinaryWriter)bamlBinaryWriter).Write7BitEncodedInt(RecordSize); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlVariableSizedRecord newRecord = (BamlVariableSizedRecord)record; newRecord._recordSize = _recordSize; } #endif #endregion Methods #region Properties // Actual size of the complete BamlRecord in bytes. Currently // limited to 2 gigabytes. internal override Int32 RecordSize { get { return _recordSize; } set { _recordSize = value; } } // This provides subclasses with a referece section to create their own section. internal new static BitVector32.Section LastFlagsSection { get { return BamlRecord.LastFlagsSection; } } #endregion Properties #region Data // Size of the RecordSize field in the baml file. This must be in // [....] the type type of _recordSize below. internal const int MaxRecordSizeFieldLength = 4; Int32 _recordSize = -1; // we use a 7 bit encoded variable size #endregion Data } //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlXmlnsPropertyRecord : BamlVariableSizedRecord { #region Methods #if !PBTCOMPILER // LoadRecord specific data internal override void LoadRecordData(BinaryReader bamlBinaryReader) { Prefix = bamlBinaryReader.ReadString(); XmlNamespace = bamlBinaryReader.ReadString(); short count = bamlBinaryReader.ReadInt16(); if (count > 0) { AssemblyIds = new short[count]; for (short i = 0; i < count; i++) { AssemblyIds[i] = bamlBinaryReader.ReadInt16(); } } else { AssemblyIds = null; } } #endif // write record specific Data. internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(Prefix); bamlBinaryWriter.Write(XmlNamespace); // Write the AssemblyIds which contain XmlnsDefinitionAttribute // for this xmlns Uri. // The format should be CountN Id1 Id2 ... IdN // short count = 0; if (AssemblyIds != null && AssemblyIds.Length > 0) { count = (short) AssemblyIds.Length; } bamlBinaryWriter.Write(count); if (count > 0) { for (short i = 0; i < count; i++) { bamlBinaryWriter.Write(AssemblyIds[i]); } } } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlXmlnsPropertyRecord newRecord = (BamlXmlnsPropertyRecord)record; newRecord._prefix = _prefix; newRecord._xmlNamespace = _xmlNamespace; newRecord._assemblyIds = _assemblyIds; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.XmlnsProperty; } } internal string Prefix { get { return _prefix; } set {_prefix = value; } } internal string XmlNamespace { get { return _xmlNamespace; } set { _xmlNamespace = value; } } internal short[] AssemblyIds { get { return _assemblyIds; } set { _assemblyIds = value; } } #endregion Properties #region Data string _prefix; string _xmlNamespace; short[] _assemblyIds; #endregion Data } //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPIMappingRecord : BamlVariableSizedRecord { #region Methods #if !PBTCOMPILER // LoadRecord specific data internal override void LoadRecordData(BinaryReader bamlBinaryReader) { XmlNamespace = bamlBinaryReader.ReadString(); ClrNamespace = bamlBinaryReader.ReadString(); AssemblyId = bamlBinaryReader.ReadInt16(); } #endif // write record specific Data. internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { // write out an int for record size but we'll go back and fill bamlBinaryWriter.Write(XmlNamespace); bamlBinaryWriter.Write(ClrNamespace); bamlBinaryWriter.Write(AssemblyId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlPIMappingRecord newRecord = (BamlPIMappingRecord)record; newRecord._xmlns = _xmlns; newRecord._clrns = _clrns; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PIMapping; } } internal string XmlNamespace { get { return _xmlns; } set {_xmlns = value; } } internal string ClrNamespace { get { return _clrns; } set { _clrns = value; } } internal short AssemblyId { get { short value = (short) _flags[_assemblyIdLowSection]; value |= (short) (_flags[_assemblyIdHighSection] << 8); return value; } set { _flags[_assemblyIdLowSection] = (short) (value & 0xff); _flags[_assemblyIdHighSection] = (short) ((value & 0xff00) >> 8); } } // Allocate space in _flags. // BitVector32 doesn't support 16 bit sections, so we have to break // it up into 2 sections. private static BitVector32.Section _assemblyIdLowSection = BitVector32.CreateSection( (short)0xff, BamlVariableSizedRecord.LastFlagsSection ); private static BitVector32.Section _assemblyIdHighSection = BitVector32.CreateSection( (short)0xff, _assemblyIdLowSection ); #if !PBTCOMPILER // This provides subclasses with a referece section to create their own section. internal new static BitVector32.Section LastFlagsSection { get { return _assemblyIdHighSection; } } #endif #endregion Properties #region Data string _xmlns; string _clrns; #endregion Data } // Common base class for variables sized records that contain a string value //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal abstract class BamlStringValueRecord : BamlVariableSizedRecord { #region Methods #if !PBTCOMPILER // LoadRecord specific data internal override void LoadRecordData(BinaryReader bamlBinaryReader) { Value = bamlBinaryReader.ReadString(); } #endif // write record specific Data. internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(Value); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlStringValueRecord newRecord = (BamlStringValueRecord)record; newRecord._value = _value; } #endif #endregion Methods #region Properties internal string Value { get { return _value; } set { _value = value; } } #endregion Properties #region Data string _value; #endregion Data } // Common methods for baml records that serve as keys in a dictionary. internal interface IBamlDictionaryKey { // Update the pointer to the Value that was written out when WriteRecordData // was first called. void UpdateValuePosition( Int32 newPosition, BinaryWriter bamlBinaryWriter); // Relative stream position in the baml stream where the value associated // with this key starts. It is relative to the end of the keys section, // or the start of the values section. Int32 ValuePosition { get; set; } // The actual key object used in the dictionary. This may be a string, // field, type or other object. object KeyObject { get; set; } // Position in the stream where ValuePosition was written. This is needed // when updating the ValuePosition. Int64 ValuePositionPosition { get; set; } // True if the value associated with this key is shared. bool Shared { get; set; } // Whether Shared was set. bool SharedSet { get; set; } #if !PBTCOMPILER object[] StaticResourceValues {get; set;} #endif } // Common interface implemented by BamlRecords that // use optimized storage for MarkupExtensions. internal interface IOptimizedMarkupExtension { short ExtensionTypeId { get; } short ValueId { get; } bool IsValueTypeExtension { get; } bool IsValueStaticExtension { get; } } // BamlRecord use in a defer loaded dictionary as the key for adding a value. // The value is a type that is refered to using a TypeID //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlDefAttributeKeyTypeRecord : BamlElementStartRecord, IBamlDictionaryKey { internal BamlDefAttributeKeyTypeRecord() { Pin(); // Don't allow this record to be recycled in the read cache. } #region Methods #if !PBTCOMPILER // LoadRecord specific data internal override void LoadRecordData(BinaryReader bamlBinaryReader) { base.LoadRecordData(bamlBinaryReader); _valuePosition = bamlBinaryReader.ReadInt32(); ((IBamlDictionaryKey)this).Shared = bamlBinaryReader.ReadBoolean(); ((IBamlDictionaryKey)this).SharedSet = bamlBinaryReader.ReadBoolean(); } #endif // Write record specific Data. internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { base.WriteRecordData(bamlBinaryWriter); _valuePositionPosition = bamlBinaryWriter.Seek(0, SeekOrigin.Current); bamlBinaryWriter.Write(_valuePosition); bamlBinaryWriter.Write(((IBamlDictionaryKey)this).Shared); bamlBinaryWriter.Write(((IBamlDictionaryKey)this).SharedSet); } // Update the pointer to the Value that was written out when WriteRecordData // was first called. At that time the true position was probably not known, // so it is written out later. Be certain to leave the passed writer pointing // to the same location it was at when this call was made. void IBamlDictionaryKey.UpdateValuePosition( Int32 newPosition, BinaryWriter bamlBinaryWriter) { Debug.Assert(_valuePositionPosition != -1, "Must call WriteRecordData before updating position"); // Use relative positions to reduce the possibility of truncation, // since Seek takes a 32 bit int, but position is a 64 bit int. Int64 existingPosition = bamlBinaryWriter.Seek(0, SeekOrigin.Current); Int32 deltaPosition = (Int32)(_valuePositionPosition-existingPosition); bamlBinaryWriter.Seek(deltaPosition, SeekOrigin.Current); bamlBinaryWriter.Write(newPosition); bamlBinaryWriter.Seek(-ValuePositionSize-deltaPosition, SeekOrigin.Current); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlDefAttributeKeyTypeRecord newRecord = (BamlDefAttributeKeyTypeRecord)record; newRecord._valuePosition = _valuePosition; newRecord._valuePositionPosition = _valuePositionPosition; newRecord._keyObject = _keyObject; newRecord._staticResourceValues = _staticResourceValues; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.DefAttributeKeyType; } } // Relative stream position in the baml stream where the value associated // with this key starts. It is relative to the end of the keys section, // or the start of the values section. Int32 IBamlDictionaryKey.ValuePosition { get { return _valuePosition; } set { _valuePosition = value; } } // The actual key used in the defer loaded dictionary. For this type of // record the key is a Type that is obtained at runtime from the base // classes TypeId object IBamlDictionaryKey.KeyObject { get { return _keyObject; } set { _keyObject = value; } } // Position in the stream where ValuePosition was written. This is needed // when updating the ValuePosition. Int64 IBamlDictionaryKey.ValuePositionPosition { get { return _valuePositionPosition; } set { _valuePositionPosition = value; } } // True if the value associated with this key is shared. bool IBamlDictionaryKey.Shared { get { return _flags[_sharedSection] == 1 ? true : false; } set { _flags[_sharedSection] = value ? 1 : 0; } } // Whether Shared was set bool IBamlDictionaryKey.SharedSet { get { return _flags[_sharedSetSection] == 1 ? true : false; } set { _flags[_sharedSetSection] = value ? 1 : 0; } } #if !PBTCOMPILER object[] IBamlDictionaryKey.StaticResourceValues { get { return _staticResourceValues; } set { _staticResourceValues = value; } } #endif // Allocate space in _flags. private static BitVector32.Section _sharedSection = BitVector32.CreateSection( 1, BamlElementStartRecord.LastFlagsSection ); private static BitVector32.Section _sharedSetSection = BitVector32.CreateSection( 1, _sharedSection ); #if !PBTCOMPILER // This provides subclasses with a referece section to create their own section. internal new static BitVector32.Section LastFlagsSection { get { return _sharedSetSection; } } #endif #endregion Properties #region Data // Size in bytes of the ValuePosition field written out to baml. This // must be in [....] with the size of _valuePosition below. internal const Int32 ValuePositionSize = 4; // Relative position in the stream where the value associated with this key starts Int32 _valuePosition; // Position in the stream where ValuePosition was written. This is needed // when updating the ValuePosition. Int64 _valuePositionPosition = -1; // Actual object key used by a dictionary. This is a Type object object _keyObject = null; #if !PBTCOMPILER object[] _staticResourceValues; #endif #endregion Data } // BamlRecord for x:Key attribute when used in a defer loaded dictionary // as the key for adding a value. The value is stored as a string. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlDefAttributeKeyStringRecord : BamlStringValueRecord, IBamlDictionaryKey { internal BamlDefAttributeKeyStringRecord() { Pin(); // Don't allow this record to be recycled in the read cache. } #region Methods #if !PBTCOMPILER // LoadRecord specific data internal override void LoadRecordData(BinaryReader bamlBinaryReader) { ValueId = bamlBinaryReader.ReadInt16(); _valuePosition = bamlBinaryReader.ReadInt32(); ((IBamlDictionaryKey)this).Shared = bamlBinaryReader.ReadBoolean(); ((IBamlDictionaryKey)this).SharedSet = bamlBinaryReader.ReadBoolean(); _keyObject = null; } #endif // Write record specific Data. internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(ValueId); _valuePositionPosition = bamlBinaryWriter.Seek(0, SeekOrigin.Current); bamlBinaryWriter.Write(_valuePosition); bamlBinaryWriter.Write(((IBamlDictionaryKey)this).Shared); bamlBinaryWriter.Write(((IBamlDictionaryKey)this).SharedSet); } // Update the pointer to the Value that was written out when WriteRecordData // was first called. At that time the true position was probably not known, // so it is written out later. Be certain to leave the passed writer pointing // to the same location it was at when this call was made. void IBamlDictionaryKey.UpdateValuePosition( Int32 newPosition, BinaryWriter bamlBinaryWriter) { Debug.Assert(_valuePositionPosition != -1, "Must call WriteRecordData before updating position"); // Use relative positions to reduce the possibility of truncation, // since Seek takes a 32 bit int, but position is a 64 bit int. Int64 existingPosition = bamlBinaryWriter.Seek(0, SeekOrigin.Current); Int32 deltaPosition = (Int32)(_valuePositionPosition-existingPosition); bamlBinaryWriter.Seek(deltaPosition, SeekOrigin.Current); bamlBinaryWriter.Write(newPosition); bamlBinaryWriter.Seek(-ValuePositionSize-deltaPosition, SeekOrigin.Current); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlDefAttributeKeyStringRecord newRecord = (BamlDefAttributeKeyStringRecord)record; newRecord._valuePosition = _valuePosition; newRecord._valuePositionPosition = _valuePositionPosition; newRecord._keyObject = _keyObject; newRecord._valueId = _valueId; newRecord._staticResourceValues = _staticResourceValues; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.DefAttributeKeyString; } } // Relative stream position in the baml stream where the value associated // with this key starts. It is relative to the end of the keys section, // or the start of the values section. Int32 IBamlDictionaryKey.ValuePosition { get { return _valuePosition; } set { _valuePosition = value; } } // True if the value associated with this key is shared. bool IBamlDictionaryKey.Shared { get { return _flags[_sharedSection] == 1 ? true : false; } set { _flags[_sharedSection] = value ? 1 : 0; } } // Whether Shared was set bool IBamlDictionaryKey.SharedSet { get { return _flags[_sharedSetSection] == 1 ? true : false; } set { _flags[_sharedSetSection] = value ? 1 : 0; } } // Allocate space in _flags. private static BitVector32.Section _sharedSection = BitVector32.CreateSection( 1, BamlStringValueRecord.LastFlagsSection ); private static BitVector32.Section _sharedSetSection = BitVector32.CreateSection( 1, _sharedSection ); #if !PBTCOMPILER // This provides subclasses with a referece section to create their own section. internal new static BitVector32.Section LastFlagsSection { get { return _sharedSetSection; } } #endif // The following are NOT written out to BAML but are cached at runtime // The string value translated into a key object. The string may represent // a type, field, or other object that can be translated into an object using // using the Mapper. object IBamlDictionaryKey.KeyObject { get { return _keyObject; } set { _keyObject = value; } } // Position in the stream where ValuePosition was written. This is needed // when updating the ValuePosition. Int64 IBamlDictionaryKey.ValuePositionPosition { get { return _valuePositionPosition; } set { _valuePositionPosition = value; } } internal Int16 ValueId { get { return _valueId; } set { _valueId = value; } } #if !PBTCOMPILER object[] IBamlDictionaryKey.StaticResourceValues { get { return _staticResourceValues; } set { _staticResourceValues = value; } } #endif #endregion Properties #region Data // Size in bytes of the ValuePosition field written out to baml. This // must be in [....] with the size of _valuePosition below. internal const Int32 ValuePositionSize = 4; // Relative position in the stream where the value associated with this key starts Int32 _valuePosition; // Position in the stream where ValuePosition was written. This is needed // when updating the ValuePosition. Int64 _valuePositionPosition = -1; // Actual object key used by a dictionary. This is the Value string // after conversion. object _keyObject = null; Int16 _valueId; #if !PBTCOMPILER object[] _staticResourceValues; #endif #endregion Data } // BamlRecord for x:Whatever attribute //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlDefAttributeRecord : BamlStringValueRecord { #region Methods #if !PBTCOMPILER // LoadRecord specific data internal override void LoadRecordData(BinaryReader bamlBinaryReader) { Value = bamlBinaryReader.ReadString(); NameId = bamlBinaryReader.ReadInt16(); Name = null; } #endif // write record specific Data. internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(Value); bamlBinaryWriter.Write(NameId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlDefAttributeRecord newRecord = (BamlDefAttributeRecord)record; newRecord._name = _name; newRecord._nameId = _nameId; newRecord._attributeUsage = _attributeUsage; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.DefAttribute; } } // The following is written out the baml file. internal Int16 NameId { get { return _nameId; } set { _nameId = value; } } // The following are cached locally, but not written to baml. internal string Name { #if !PBTCOMPILER get { return _name; } #endif set { _name = value; } } // Some attributes have special usage, such as setting the XmlLang and XmlSpace // strings in the parser context. This is flagged with this property internal BamlAttributeUsage AttributeUsage { #if !PBTCOMPILER get { return _attributeUsage; } #endif set { _attributeUsage = value; } } #endregion Properties #if !PBTCOMPILER public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0} nameId({1}) is '{2}' usage={3}", RecordType, NameId, Name, AttributeUsage); } #endif #region Data string _name; Int16 _nameId; BamlAttributeUsage _attributeUsage; #endregion Data } // BamlRecord for PresentationOptions:Whatever attribute //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPresentationOptionsAttributeRecord : BamlStringValueRecord { #region Methods #if !PBTCOMPILER // LoadRecord specific data internal override void LoadRecordData(BinaryReader bamlBinaryReader) { Value = bamlBinaryReader.ReadString(); NameId = bamlBinaryReader.ReadInt16(); Name = null; } #endif // write record specific Data. internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(Value); bamlBinaryWriter.Write(NameId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlPresentationOptionsAttributeRecord newRecord = (BamlPresentationOptionsAttributeRecord)record; newRecord._name = _name; newRecord._nameId = _nameId; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PresentationOptionsAttribute; } } // The following is written out the baml file. internal Int16 NameId { get { return _nameId; } set { _nameId = value; } } // The following are cached locally, but not written to baml. internal string Name { #if !PBTCOMPILER get { return _name; } #endif set { _name = value; } } #endregion Properties #if !PBTCOMPILER public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0} nameId({1}) is '{2}' ", RecordType, NameId, Name); } #endif #region Data string _name; Int16 _nameId; #endregion Data } // // BamlPropertyComplexStartRecord is for Complex DependencyProperty declarations // in markup, where the actual type and value is determined by subsequent records. // //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyComplexStartRecord : BamlRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { AttributeId = bamlBinaryReader.ReadInt16(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(AttributeId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlPropertyComplexStartRecord newRecord = (BamlPropertyComplexStartRecord)record; newRecord._attributeId = _attributeId; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyComplexStart; } } internal short AttributeId { get { return _attributeId; } set { _attributeId = value; } } internal override Int32 RecordSize { get { return 2; } set { Debug.Assert (value == -1, "Wrong size set for complex prop record"); } } #endregion Properties #if !PBTCOMPILER public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0} attr({1})", RecordType, _attributeId); } #endif #region Data short _attributeId = -1; #endregion Data } // // BamlPropertyStringReferenceRecord is for Property values that are written // out as references into the string table. // //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyStringReferenceRecord : BamlPropertyComplexStartRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { AttributeId = bamlBinaryReader.ReadInt16(); StringId = bamlBinaryReader.ReadInt16(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(AttributeId); bamlBinaryWriter.Write(StringId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlPropertyStringReferenceRecord newRecord = (BamlPropertyStringReferenceRecord)record; newRecord._stringId = _stringId; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyStringReference; } } internal short StringId { get { return _stringId; } #if !PBTCOMPILER set { _stringId = value; } #endif } internal override Int32 RecordSize { get { return 4; } set { Debug.Assert (value == -1, "Wrong size set for complex prop record"); } } #endregion Properties #region Data short _stringId = 0; #endregion Data } // // BamlPropertyTypeReferenceRecord is for Property values that are written // out as references into the type table. So the property value is a 'Type' object. // //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyTypeReferenceRecord : BamlPropertyComplexStartRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { AttributeId = bamlBinaryReader.ReadInt16(); TypeId = bamlBinaryReader.ReadInt16(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(AttributeId); bamlBinaryWriter.Write(TypeId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlPropertyTypeReferenceRecord newRecord = (BamlPropertyTypeReferenceRecord)record; newRecord._typeId = _typeId; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyTypeReference; } } internal short TypeId { get { return _typeId; } set { _typeId = value; } } internal override Int32 RecordSize { get { return 4; } set { Debug.Assert (value == -1, "Wrong size set for complex prop record"); } } #endregion Properties #region Data short _typeId = 0; #endregion Data } // // BamlPropertyWithConverterRecord information for property with custom type converter // //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyWithConverterRecord : BamlPropertyRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { base.LoadRecordData(bamlBinaryReader); ConverterTypeId = bamlBinaryReader.ReadInt16(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { base.WriteRecordData(bamlBinaryWriter); bamlBinaryWriter.Write(ConverterTypeId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlPropertyWithConverterRecord newRecord = (BamlPropertyWithConverterRecord)record; newRecord._converterTypeId = _converterTypeId; } #endif #endregion Methods #region Properties // The following are stored in the baml stream // ID of this type converter. Referenced in other baml records where a // Type is needed. internal short ConverterTypeId { get { return _converterTypeId; } set { _converterTypeId = value; } } // Additional properties not stored in the baml stream internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyWithConverter; } } #endregion Properties #region Data short _converterTypeId = 0; #endregion Data } // // BamlPropertyRecord is for DependencyProperty values that are written // out as strings. // //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyRecord : BamlStringValueRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { AttributeId = bamlBinaryReader.ReadInt16(); Value = bamlBinaryReader.ReadString(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(AttributeId); bamlBinaryWriter.Write(Value); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlPropertyRecord newRecord = (BamlPropertyRecord)record; newRecord._attributeId = _attributeId; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.Property; } } internal short AttributeId { get { return _attributeId; } set { _attributeId = value; } } #endregion Properties #if !PBTCOMPILER public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0} attr({1}) <== '{2}'", RecordType, _attributeId, Value); } #endif #region Data short _attributeId = -1; #endregion Data } // // BamlPropertyWithExtensionRecord is for property values that are Markup extensions // with a single param member that are written out as attributeIds. // //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyWithExtensionRecord : BamlRecord, IOptimizedMarkupExtension { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { AttributeId = bamlBinaryReader.ReadInt16(); short extensionTypeId = bamlBinaryReader.ReadInt16(); ValueId = bamlBinaryReader.ReadInt16(); // The upper 4 bits of the ExtensionTypeId are used as flags _extensionTypeId = (short)(extensionTypeId & ExtensionIdMask); IsValueTypeExtension = (extensionTypeId & TypeExtensionValueMask) == TypeExtensionValueMask; IsValueStaticExtension = (extensionTypeId & StaticExtensionValueMask) == StaticExtensionValueMask; } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(AttributeId); short extensionTypeId = ExtensionTypeId; if (IsValueTypeExtension) { extensionTypeId |= TypeExtensionValueMask; } else if (IsValueStaticExtension) { extensionTypeId |= StaticExtensionValueMask; } bamlBinaryWriter.Write(extensionTypeId); bamlBinaryWriter.Write(ValueId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlPropertyWithExtensionRecord newRecord = (BamlPropertyWithExtensionRecord)record; newRecord._attributeId = _attributeId; newRecord._extensionTypeId = _extensionTypeId; newRecord._valueId = _valueId; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyWithExtension; } } // Id of the property whose value is the simple ME internal short AttributeId { get { return _attributeId; } set { _attributeId = value; } } // KnownElement Id of the MarkupExtension public short ExtensionTypeId { get { return _extensionTypeId; } set { // we shouldn't ever be intruding on the flags portion of the ExtensionTypeId Debug.Assert(value <= ExtensionIdMask); _extensionTypeId = value; } } // For StaticExtension: AttributeId of a member // For TemplateBindingExtension: AttributeId of a DependencyProperty // For a DynamicResourceExtension: // StringId if the value is a string // TypeId if the value is a TypeExtension // AttributeId of the member if the value is a StaticExtension public short ValueId { get { return _valueId; } set { _valueId = value; } } internal override Int32 RecordSize { get { return 6; } set { Debug.Assert(value == -1, "Wrong size set for complex prop record"); } } // For DynamicResourceExtension, if the value is itself a simple TypeExtension public bool IsValueTypeExtension { get { return _flags[_isValueTypeExtensionSection] == 1 ? true : false; } set { _flags[_isValueTypeExtensionSection] = value ? 1 : 0; } } // For DynamicResourceExtension, if the value is itself a simple StaticExtension public bool IsValueStaticExtension { get { return _flags[_isValueStaticExtensionSection] == 1 ? true : false; } set { _flags[_isValueStaticExtensionSection] = value ? 1 : 0; } } // Allocate space in _flags. private static BitVector32.Section _isValueTypeExtensionSection = BitVector32.CreateSection(1, BamlRecord.LastFlagsSection); private static BitVector32.Section _isValueStaticExtensionSection = BitVector32.CreateSection(1, _isValueTypeExtensionSection); #if !PBTCOMPILER // This provides subclasses with a referece section to create their own section. internal new static BitVector32.Section LastFlagsSection { get { return _isValueStaticExtensionSection; } } public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0} attr({1}) extn({2}) valueId({3})", RecordType, _attributeId, _extensionTypeId, _valueId); } #endif #endregion Properties #region Data short _attributeId = -1; short _extensionTypeId = 0; short _valueId = 0; private static readonly short ExtensionIdMask = 0x0FFF; private static readonly short TypeExtensionValueMask = 0x4000; private static readonly short StaticExtensionValueMask = 0x2000; #endregion Data } // // BamlPropertyCustomWriteInfoRecord is for DependencyProperty values that support // custom Avalon serialization. The property value objects write directly onto // the BAML stream in whatever format they understand. This record is used only // during BAML write time. // //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyCustomWriteInfoRecord : BamlPropertyCustomRecord { internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { int writePositionStart = (int)bamlBinaryWriter.Seek(0, SeekOrigin.Current); short serializerTypeId = SerializerTypeId; bamlBinaryWriter.Write(AttributeId); if (serializerTypeId == (short)KnownElements.DependencyPropertyConverter) { // There is no need to actually use a real Converter here since we already have the // DP value as an AttributeInfoId. // if ValueMemberName exists then remember that the ValueId is a TypeId of the // type that declares ValueMemberName, so that it can be resolved correctly at // load time. if (ValueMemberName != null) { bamlBinaryWriter.Write((short)(serializerTypeId | TypeIdValueMask)); } else { bamlBinaryWriter.Write(serializerTypeId); } // if ValueMemberName does not exist, ValueId is a KnownProperty Id // else it is a TypeId of the declaring type. bamlBinaryWriter.Write(ValueId); // Write out the ValueMemberName if it exists if (ValueMemberName != null) { bamlBinaryWriter.Write(ValueMemberName); } return; } bamlBinaryWriter.Write(serializerTypeId); bool converted = false; // If we have an enum or a bool, do conversion to custom binary data here, // since we do not have a serializer associated with these types. if (ValueType != null && ValueType.IsEnum) { uint uintValue = 0; string [] enumValues = Value.Split(new Char[] { ',' }); // if the Enum is a flag, then resolve each flag value in the enum value string. foreach (string enumValue in enumValues) { FieldInfo enumField = ValueType.GetField(enumValue.Trim(), BindingFlags.Static | BindingFlags.Public | BindingFlags.IgnoreCase); if (enumField != null) { // get the raw va;ue of the enum field and convert to a uint. object rawEnumValue = enumField.GetRawConstantValue(); uintValue += (uint)Convert.ChangeType(rawEnumValue, typeof(uint), TCH.EnglishUSCulture); converted = true; } else { converted = false; break; } } if (converted) { bamlBinaryWriter.Write(uintValue); } } else if (ValueType == typeof(Boolean)) { TypeConverter boolConverter = TypeDescriptor.GetConverter(typeof(Boolean)); object convertedValue = boolConverter.ConvertFromString(TypeContext, TCH.EnglishUSCulture, Value); bamlBinaryWriter.Write((byte)Convert.ChangeType(convertedValue, typeof(byte), TCH.EnglishUSCulture)); converted = true; } else if (SerializerType == typeof(XamlBrushSerializer)) { XamlSerializer serializer = new XamlBrushSerializer(); // If we custom serialize this particular value at this point, then see // if it can convert. // NOTE: This is sensitive to changes in the BamlRecordWriter and // BamlRecordManager code and must be kept in [....] with them... converted = serializer.ConvertStringToCustomBinary(bamlBinaryWriter, Value); } else if (SerializerType == typeof(XamlPoint3DCollectionSerializer)) { XamlSerializer serializer = new XamlPoint3DCollectionSerializer(); // If we custom serialize this particular value at this point, then see // if it can convert. // NOTE: This is sensitive to changes in the BamlRecordWriter and // BamlRecordManager code and must be kept in [....] with them... converted = serializer.ConvertStringToCustomBinary(bamlBinaryWriter, Value); } else if (SerializerType == typeof(XamlVector3DCollectionSerializer)) { XamlSerializer serializer = new XamlVector3DCollectionSerializer(); // If we custom serialize this particular value at this point, then see // if it can convert. // NOTE: This is sensitive to changes in the BamlRecordWriter and // BamlRecordManager code and must be kept in [....] with them... converted = serializer.ConvertStringToCustomBinary(bamlBinaryWriter, Value); } else if (SerializerType == typeof(XamlPointCollectionSerializer)) { XamlSerializer serializer = new XamlPointCollectionSerializer(); // If we custom serialize this particular value at this point, then see // if it can convert. // NOTE: This is sensitive to changes in the BamlRecordWriter and // BamlRecordManager code and must be kept in [....] with them... converted = serializer.ConvertStringToCustomBinary(bamlBinaryWriter, Value); } else if (SerializerType == typeof(XamlInt32CollectionSerializer)) { XamlSerializer serializer = new XamlInt32CollectionSerializer(); // If we custom serialize this particular value at this point, then see // if it can convert. // NOTE: This is sensitive to changes in the BamlRecordWriter and // BamlRecordManager code and must be kept in [....] with them... converted = serializer.ConvertStringToCustomBinary(bamlBinaryWriter, Value); } else if (SerializerType == typeof(XamlPathDataSerializer)) { XamlSerializer serializer = new XamlPathDataSerializer(); // If we custom serialize this particular value at this point, then see // if it can convert. // NOTE: This is sensitive to changes in the BamlRecordWriter and // BamlRecordManager code and must be kept in [....] with them... converted = serializer.ConvertStringToCustomBinary(bamlBinaryWriter, Value); } if (!converted) { throw new XamlParseException(SR.Get(SRID.ParserBadString, Value, ValueType.Name)); } } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlPropertyCustomWriteInfoRecord newRecord = (BamlPropertyCustomWriteInfoRecord)record; newRecord._valueId = _valueId; newRecord._valueType = _valueType; newRecord._value = _value; newRecord._valueMemberName = _valueMemberName; newRecord._serializerType = _serializerType; newRecord._typeContext = _typeContext; } #endif // The KnownProperty Id of the Value, if it is a property and can be converted into one, // or the TypeId of the owner of the property value internal short ValueId { get { return _valueId; } set { _valueId = value; } } // If ValueId is a TypeId, then this holds the name of the member. internal string ValueMemberName { get { return _valueMemberName; } set { _valueMemberName = value; } } // The following properties are NOT written to the BAML stream. // Type of this property internal Type ValueType { get { return _valueType; } set { _valueType = value; } } // The string Value of the property. internal string Value { get { return _value; } set { _value = value; } } // Type of the XamlSerializer associated with this property. Null // if this type is custom serialized by the parser itself. internal Type SerializerType { get { return _serializerType; } set { _serializerType = value; } } // Context used for type conversion of built in types. internal ITypeDescriptorContext TypeContext { get { return _typeContext; } set { _typeContext = value; } } short _valueId; Type _valueType; string _value; string _valueMemberName; Type _serializerType; ITypeDescriptorContext _typeContext; } // // BamlPropertyCustomRecord is for DependencyProperty values that support // custom Avalon serialization. This record is used only during BAML load. // The property value objects are read directly from the BAML stream by the // custom binary serializer for the property. // //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyCustomRecord : BamlVariableSizedRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { AttributeId = bamlBinaryReader.ReadInt16(); short serializerTypeId = bamlBinaryReader.ReadInt16(); IsValueTypeId = (serializerTypeId & TypeIdValueMask) == TypeIdValueMask; if (IsValueTypeId) { serializerTypeId &= (short)(~TypeIdValueMask); } SerializerTypeId = serializerTypeId; ValueObjectSet = false; IsRawEnumValueSet = false; _valueObject = null; // ValueObject and ValueObject are not set until BamlRecordReader.ReadPropertyCustomRecord // because the Mapper is needed for custom DPs // NOTE: above may no longer true, so this could be potentially changed to be in [....] with // other record. Needs more investigation. } // Read the binary data using the passed reader and use that to set the ValueObject. internal object GetCustomValue(BinaryReader reader, Type propertyType, short serializerId, BamlRecordReader bamlRecordReader) { Debug.Assert(!ValueObjectSet); // Handle enums and bools here directly. // Otherwise call the known custom serializers directly. switch (serializerId) { case (short)KnownElements.EnumConverter: uint enumBits; if (_valueObject == null) { // if no raw value has been read in yet, read it now // from the baml stream. enumBits = reader.ReadUInt32(); } else { // raw value has been read in earlier, so try to resolve into // an actual enum value now. enumBits = (uint)_valueObject; } if (propertyType.IsEnum) { // property Type is an enum, so raw value can be resolved now. _valueObject = Enum.ToObject(propertyType, enumBits); ValueObjectSet = true; IsRawEnumValueSet = false; } else { // property Type is not available yet, so raw value cannot // be resolved now. Store it and try later. _valueObject = enumBits; ValueObjectSet = false; IsRawEnumValueSet = true; } return _valueObject; case (short)KnownElements.BooleanConverter: byte boolByte = reader.ReadByte(); _valueObject = boolByte == 1; break; case (short)KnownElements.XamlBrushSerializer: // Don't bother creating a XamlBrushSerializer instance & calling ConvertCustomBinaryToObject // on it since that just calls SCB directly liek below. This saves big on perf. _valueObject = SolidColorBrush.DeserializeFrom(reader, bamlRecordReader.TypeConvertContext); break; case (short)KnownElements.XamlPathDataSerializer: _valueObject = XamlPathDataSerializer.StaticConvertCustomBinaryToObject(reader); break; case (short)KnownElements.XamlPoint3DCollectionSerializer: _valueObject = XamlPoint3DCollectionSerializer.StaticConvertCustomBinaryToObject(reader); break; case (short)KnownElements.XamlVector3DCollectionSerializer: _valueObject = XamlVector3DCollectionSerializer.StaticConvertCustomBinaryToObject(reader); break; case (short)KnownElements.XamlPointCollectionSerializer: _valueObject = XamlPointCollectionSerializer.StaticConvertCustomBinaryToObject(reader); break; case (short)KnownElements.XamlInt32CollectionSerializer: _valueObject = XamlInt32CollectionSerializer.StaticConvertCustomBinaryToObject(reader); break; default: Debug.Assert (false, "Unknown custom serializer"); return null; } ValueObjectSet = true; return _valueObject; } internal override void Copy(BamlRecord record) { base.Copy(record); BamlPropertyCustomRecord newRecord = (BamlPropertyCustomRecord)record; newRecord._valueObject = _valueObject; newRecord._attributeId = _attributeId; newRecord._serializerTypeId = _serializerTypeId; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyCustom; } } internal short AttributeId { get { return _attributeId; } set { _attributeId = value; } } // ID of this serializer type. Referenced in other baml records where a // Type is needed. internal short SerializerTypeId { get { return _serializerTypeId; } set { _serializerTypeId = value; } } // The following properties are NOT written to the BAML stream. #if !PBTCOMPILER // Value of the converted object. internal object ValueObject { get { return _valueObject; } set { _valueObject = value; } } // Return true if GetCustomValue has been called, indicating that // a conversion from binary custom data to a ValueObject has occurred. internal bool ValueObjectSet { get { return _flags[_isValueSetSection] == 1 ? true : false; } set { _flags[_isValueSetSection] = value ? 1 : 0; } } internal bool IsValueTypeId { get { return _flags[_isValueTypeIdSection] == 1 ? true : false; } set { _flags[_isValueTypeIdSection] = value ? 1 : 0; } } // true if only the raw value of enum has been read as it cannot yet be // converted into an enum as the Type is not available yet. internal bool IsRawEnumValueSet { get { return _flags[_isRawEnumValueSetSection] == 1 ? true : false; } set { _flags[_isRawEnumValueSetSection] = value ? 1 : 0; } } object _valueObject; // Allocate space in _flags. private static BitVector32.Section _isValueSetSection = BitVector32.CreateSection(1, BamlVariableSizedRecord.LastFlagsSection); // Allocate space in _flags. private static BitVector32.Section _isValueTypeIdSection = BitVector32.CreateSection(1, _isValueSetSection); // Allocate space in _flags. private static BitVector32.Section _isRawEnumValueSetSection = BitVector32.CreateSection(1, _isValueTypeIdSection); // This provides subclasses with a referece section to create their own section. internal new static BitVector32.Section LastFlagsSection { get { return _isRawEnumValueSetSection; } } #endif #endregion Properties #region Data internal static readonly short TypeIdValueMask = 0x4000; short _attributeId = 0; short _serializerTypeId = 0; #endregion Data } //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyArrayEndRecord : BamlRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyArrayEnd; } } #endregion Properties } //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlConstructorParametersStartRecord : BamlRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.ConstructorParametersStart; } } #endregion Properties } //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlConstructorParametersEndRecord : BamlRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.ConstructorParametersEnd; } } #endregion Properties } //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlConstructorParameterTypeRecord : BamlRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { TypeId = bamlBinaryReader.ReadInt16(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(TypeId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlConstructorParameterTypeRecord newRecord = (BamlConstructorParameterTypeRecord)record; newRecord._typeId = _typeId; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.ConstructorParameterType; } } internal short TypeId { get { return _typeId; } set { _typeId = value; } } internal override Int32 RecordSize { get { return 2; } set { Debug.Assert (value == -1, "Wrong size set for complex prop record"); } } #endregion Properties #region Data short _typeId = 0; #endregion Data } //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyIListEndRecord : BamlRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyIListEnd; } } #endregion Properties } //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyIDictionaryEndRecord : BamlRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyIDictionaryEnd; } } #endregion Properties } //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyComplexEndRecord : BamlRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyComplexEnd; } } #endregion Properties } //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyArrayStartRecord : BamlPropertyComplexStartRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyArrayStart; } } #endregion Properties } //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyIListStartRecord : BamlPropertyComplexStartRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyIListStart; } } #endregion Properties } //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlPropertyIDictionaryStartRecord : BamlPropertyComplexStartRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyIDictionaryStart; } } #endregion Properties } //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlRoutedEventRecord : BamlStringValueRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { AttributeId = bamlBinaryReader.ReadInt16(); Value = bamlBinaryReader.ReadString(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(AttributeId); bamlBinaryWriter.Write(Value); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlRoutedEventRecord newRecord = (BamlRoutedEventRecord)record; newRecord._attributeId = _attributeId; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.RoutedEvent; } } internal short AttributeId { get { return _attributeId; } #if !PBTCOMPILER set { _attributeId = value; } #endif } #endregion Properties #region Data short _attributeId = -1; #endregion Data } // A section of literal content. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlLiteralContentRecord : BamlStringValueRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { Value = bamlBinaryReader.ReadString(); // Int32 _lineNumber = bamlBinaryReader.ReadInt32(); Int32 _linePosition = bamlBinaryReader.ReadInt32(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(Value); // bamlBinaryWriter.Write((Int32)0); bamlBinaryWriter.Write((Int32)0); } #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.LiteralContent; } } #endregion Properties } // An record for the connection id that the (Style)BamlRecordReader uses to // hookup an ID or event on any element in the object tree or Style visual tree. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlConnectionIdRecord : BamlRecord { #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { ConnectionId = bamlBinaryReader.ReadInt32(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(ConnectionId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlConnectionIdRecord newRecord = (BamlConnectionIdRecord)record; newRecord._connectionId = _connectionId; } #endif internal override BamlRecordType RecordType { get { return BamlRecordType.ConnectionId; } } // Id of the type of this object internal Int32 ConnectionId { get { return _connectionId; } set { _connectionId = value; } } internal override Int32 RecordSize { get { return 4; } set { Debug.Assert(value == -1, "Wrong size set for element record"); } } Int32 _connectionId = -1; } // An object record in the object tree. This can be a CLR // object or a DependencyObject. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlElementStartRecord : BamlRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { TypeId = bamlBinaryReader.ReadInt16(); byte flags = bamlBinaryReader.ReadByte(); CreateUsingTypeConverter = (flags & 1) != 0; IsInjected = (flags & 2) != 0; } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(TypeId); byte flags = (byte)((CreateUsingTypeConverter ? 1 : 0) | (IsInjected ? 2 : 0)); bamlBinaryWriter.Write(flags); } #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.ElementStart; } } // Id of the type of this object internal short TypeId { get { short value = (short) _flags[_typeIdLowSection]; value |= (short) (_flags[_typeIdHighSection] << 8); return value; } set { _flags[_typeIdLowSection] = (short) (value & 0xff); _flags[_typeIdHighSection] = (short) ((value & 0xff00) >> 8); } } // Whether this object instance is expected to be created via TypeConverter internal bool CreateUsingTypeConverter { get { return _flags[_useTypeConverter] == 1 ? true : false; } set { _flags[_useTypeConverter] = value ? 1 : 0; } } // Whether this element start record is just an injected tag that should not be processed internal bool IsInjected { get { return _flags[_isInjected] == 1 ? true : false; } set { _flags[_isInjected] = value ? 1 : 0; } } internal override Int32 RecordSize { get { return 3; } set { Debug.Assert(value == -1, "Wrong size set for element record"); } } #endregion Properties #if !PBTCOMPILER public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0} typeId={1}", RecordType, GetTypeName(TypeId)); } #endif // Allocate space in _flags. // BitVector32 doesn't support 16 bit sections, so we have to break // it up into 2 sections. private static BitVector32.Section _typeIdLowSection = BitVector32.CreateSection( (short)0xff, BamlRecord.LastFlagsSection ); private static BitVector32.Section _typeIdHighSection = BitVector32.CreateSection( (short)0xff, _typeIdLowSection ); private static BitVector32.Section _useTypeConverter = BitVector32.CreateSection( 1, _typeIdHighSection ); private static BitVector32.Section _isInjected = BitVector32.CreateSection( 1, _useTypeConverter ); // This provides subclasses with a referece section to create their own section. internal new static BitVector32.Section LastFlagsSection { get { return _isInjected; } } } //+--------------------------------------------------------------------------------------------------------------- // // BamlNamedElementStartRecord // // This is a BamlElementStartRecord that also carries an element name. // // This is currently internal, used only for templates. The original intent for this record was that // it become the new design for named objects; any object with an x:Name set, would have that name // incorporated into the element start record. But that design did not happen, instead the // property attribute are re-ordered such that the name always immediately follows the element // start record. So this should be removed, and the template code updated accordingly. (And in fact, // the template design should be updated so as not to be reliant on naming, as that is too fragile.) // //+---------------------------------------------------------------------------------------------------------------- #if !PBTCOMPILER internal class BamlNamedElementStartRecord : BamlElementStartRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { TypeId = bamlBinaryReader.ReadInt16(); RuntimeName = bamlBinaryReader.ReadString(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(TypeId); if( RuntimeName != null ) { bamlBinaryWriter.Write(RuntimeName); } } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlNamedElementStartRecord newRecord = (BamlNamedElementStartRecord)record; newRecord._isTemplateChild = _isTemplateChild; newRecord._runtimeName = _runtimeName; } #endif #endregion Methods #region Properties internal string RuntimeName { get { return _runtimeName; } set { _runtimeName = value; } } // This flag is used by templates to indicate that an ElementStart // record is for an object that will be a template child. We had to add // this to allow some validation during template application. This isn't // a good solution, because we shouldn't have this record understanding // template children. But the long-term plan is to break the template design // away from a dependence on names, at which point this whole BamlNamedElementStartRecord // will go away. private bool _isTemplateChild = false; internal bool IsTemplateChild { get { return _isTemplateChild; } set { _isTemplateChild = value; } } #endregion Properties #region Data // Id of the type of this object string _runtimeName = null; #endregion Data } #endif // Marks a block that has deferable content. This record contains the size // of the deferable section, excluding the start and end records themselves. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlDeferableContentStartRecord : BamlRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { ContentSize = bamlBinaryReader.ReadInt32(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { _contentSizePosition = bamlBinaryWriter.Seek(0, SeekOrigin.Current); bamlBinaryWriter.Write(ContentSize); } // Update the size of the content contained between the end of the start // record and the beginning of the end record. The size of the content is // usually not known when the start record is written out. internal void UpdateContentSize( Int32 contentSize, BinaryWriter bamlBinaryWriter) { Debug.Assert(_contentSizePosition != -1, "Must call WriteRecordData before updating content size"); // Use relative positions to reduce the possibility of truncation, // since Seek takes a 32 bit int, but position is a 64 bit int. Int64 existingPosition = bamlBinaryWriter.Seek(0, SeekOrigin.Current); Int32 deltaPosition = (Int32)(_contentSizePosition-existingPosition); bamlBinaryWriter.Seek(deltaPosition, SeekOrigin.Current); bamlBinaryWriter.Write(contentSize); bamlBinaryWriter.Seek((int)(-ContentSizeSize-deltaPosition), SeekOrigin.Current); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlDeferableContentStartRecord newRecord = (BamlDeferableContentStartRecord)record; newRecord._contentSize = _contentSize; newRecord._contentSizePosition = _contentSizePosition; newRecord._valuesBuffer = _valuesBuffer; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.DeferableContentStart; } } internal Int32 ContentSize { get { return _contentSize; } #if !PBTCOMPILER set { _contentSize = value; } #endif } internal override Int32 RecordSize { get { return 4; } set { Debug.Assert(value == -1, "Wrong size set for element record"); } } #if !PBTCOMPILER ////// For the case of a ResourceDictionary inside template content, we read /// the dictionary values into a byte array while creating the template /// content. Later during template instantiation when the dictionary instance /// is created we use this buffer to create a memory stream so that the /// ResourceDictionary can use it to RealizeDeferredContent. This is required /// because at template instantiation time we do not have a stream to work with. /// The reader operates on a linked list of BamlRecords. /// internal byte[] ValuesBuffer { get { return _valuesBuffer; } set { _valuesBuffer = value; } } #endif #endregion Properties #region Data // Size of the ContentSize field written out to the baml stream. This // must be kept in [....] with the size of the _contentSize field. const Int64 ContentSizeSize = 4; // Size of the content between the end of the start record and the // beginning of the end record for this element. Int32 _contentSize = - 1; // Absolute position in the stream where ContentSize is written. Int64 _contentSizePosition = -1; #if !PBTCOMPILER byte[] _valuesBuffer; #endif #endregion Data } //+--------------------------------------------------------------------------------------------------------------- // // BamlStaticResourceStartRecord // // This record marks the start of a StaticResourceExtension within the header for a deferred section. // //+---------------------------------------------------------------------------------------------------------------- internal class BamlStaticResourceStartRecord : BamlElementStartRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.StaticResourceStart; } } #endregion Properties } //+---------------------------------------------------------------------------------------------------------------- // // BamlStaticResourceEndRecord // // This record marks the end of a StaticResourceExtension within the header for a deferred section. // //+--------------------------------------------------------------------------------------------------------------- internal class BamlStaticResourceEndRecord : BamlElementEndRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.StaticResourceEnd; } } #endregion Properties } //+---------------------------------------------------------------------------------------------------------------- // // BamlOptimizedStaticResourceRecord // // This record represents an optimized StaticResourceExtension within the header for a deferred section. // //+--------------------------------------------------------------------------------------------------------------- internal class BamlOptimizedStaticResourceRecord : BamlRecord, IOptimizedMarkupExtension { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { byte flags = bamlBinaryReader.ReadByte(); ValueId = bamlBinaryReader.ReadInt16(); IsValueTypeExtension = (flags & TypeExtensionValueMask) != 0; IsValueStaticExtension = (flags & StaticExtensionValueMask) != 0; } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { byte flags = 0; if (IsValueTypeExtension) { flags |= TypeExtensionValueMask; } else if (IsValueStaticExtension) { flags |= StaticExtensionValueMask; } bamlBinaryWriter.Write(flags); bamlBinaryWriter.Write(ValueId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlOptimizedStaticResourceRecord newRecord = (BamlOptimizedStaticResourceRecord)record; newRecord._valueId = _valueId; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.OptimizedStaticResource; } } public short ExtensionTypeId { get { return (short)KnownElements.StaticResourceExtension; } } // StringId if the value is a string // TypeId if the value is a TypeExtension // AttributeId of the member if the value is a StaticExtension public short ValueId { get { return _valueId; } set { _valueId = value; } } internal override Int32 RecordSize { get { return 3; } set { Debug.Assert(value == -1, "Wrong size set for complex prop record"); } } // If the value is itself a simple TypeExtension public bool IsValueTypeExtension { get { return _flags[_isValueTypeExtensionSection] == 1 ? true : false; } set { _flags[_isValueTypeExtensionSection] = value ? 1 : 0; } } // If the value is itself a simple StaticExtension public bool IsValueStaticExtension { get { return _flags[_isValueStaticExtensionSection] == 1 ? true : false; } set { _flags[_isValueStaticExtensionSection] = value ? 1 : 0; } } #endregion Properties #region Data short _valueId = 0; private static readonly byte TypeExtensionValueMask = 0x01; private static readonly byte StaticExtensionValueMask = 0x02; // Allocate space in _flags. private static BitVector32.Section _isValueTypeExtensionSection = BitVector32.CreateSection(1, BamlRecord.LastFlagsSection); private static BitVector32.Section _isValueStaticExtensionSection = BitVector32.CreateSection(1, _isValueTypeExtensionSection); // This provides subclasses with a referece section to create their own section. internal new static BitVector32.Section LastFlagsSection { get { return _isValueStaticExtensionSection; } } #if !PBTCOMPILER public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0} extn(StaticResourceExtension) valueId({1})", RecordType, _valueId); } #endif #endregion Data } //+--------------------------------------------------------------------------------------------------------------- // // BamlStaticResourceIdRecord // // This BamlRecord is an identifier for a StaticResourceExtension within the header for a deferred section. // //+--------------------------------------------------------------------------------------------------------------- internal class BamlStaticResourceIdRecord : BamlRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { StaticResourceId = bamlBinaryReader.ReadInt16(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(StaticResourceId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlStaticResourceIdRecord newRecord = (BamlStaticResourceIdRecord)record; newRecord._staticResourceId = _staticResourceId; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.StaticResourceId; } } internal override Int32 RecordSize { get { return 2; } set { Debug.Assert(value == -1, "Wrong size set for complex prop record"); } } internal short StaticResourceId { get { return _staticResourceId; } set { _staticResourceId = value; } } #endregion Properties #region Data short _staticResourceId = -1; #if !PBTCOMPILER public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0} staticResourceId({1})", RecordType, StaticResourceId); } #endif #endregion Data } //+---------------------------------------------------------------------------------------------------------------- // // BamlPropertyWithStaticResourceIdRecord // // This BamlRecord represents a BamlPropertyRecord with a StaticResourceId as place holder for // a StaticResourceExtension within a deferred section. // //+--------------------------------------------------------------------------------------------------------------- internal class BamlPropertyWithStaticResourceIdRecord : BamlStaticResourceIdRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { AttributeId = bamlBinaryReader.ReadInt16(); StaticResourceId = bamlBinaryReader.ReadInt16(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(AttributeId); bamlBinaryWriter.Write(StaticResourceId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlPropertyWithStaticResourceIdRecord newRecord = (BamlPropertyWithStaticResourceIdRecord)record; newRecord._attributeId = _attributeId; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.PropertyWithStaticResourceId; } } internal override Int32 RecordSize { get { return 4; } set { Debug.Assert(value == -1, "Wrong size set for complex prop record"); } } // Id of the property whose value is the simple SR internal short AttributeId { get { return _attributeId; } set { _attributeId = value; } } #endregion Properties #region Data short _attributeId = -1; #if !PBTCOMPILER public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0} attr({1}) staticResourceId({2})", RecordType, AttributeId, StaticResourceId); } #endif #endregion Data } // Text content between the begin and end tag of an element. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlTextRecord : BamlStringValueRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.Text; } } #endregion Properties } // This is a text record within a [Static/Dynamic]ResourceExtension. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlTextWithIdRecord : BamlTextRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { ValueId = bamlBinaryReader.ReadInt16(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(ValueId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlTextWithIdRecord newRecord = (BamlTextWithIdRecord)record; newRecord._valueId = _valueId; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.TextWithId; } } internal Int16 ValueId { get { return _valueId; } set { _valueId = value; } } #endregion Properties #region Data Int16 _valueId; #endregion Data } // Text content between the begin and end tag of an element that will be parsed using a type converter. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlTextWithConverterRecord : BamlTextRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { base.LoadRecordData(bamlBinaryReader); ConverterTypeId = bamlBinaryReader.ReadInt16(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { base.WriteRecordData(bamlBinaryWriter); bamlBinaryWriter.Write(ConverterTypeId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlTextWithConverterRecord newRecord = (BamlTextWithConverterRecord)record; newRecord._converterTypeId = _converterTypeId; } #endif #endregion Methods #region Properties // The following are stored in the baml stream // ID of this type converter. Referenced in other baml records where a // Type is needed. internal short ConverterTypeId { get { return _converterTypeId; } set { _converterTypeId = value; } } // Additional properties not stored in the baml stream internal override BamlRecordType RecordType { get { return BamlRecordType.TextWithConverter; } } #endregion Properties #region Data short _converterTypeId = 0; #endregion Data } // Marks the start of a Baml document. This must always be the first // record in a BAML stream. It contains version information, and other // document wide directives. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlDocumentStartRecord : BamlRecord { #region Methods // Writes data at the current position. The seek pointer points // to byte after the end of record when done. internal override void Write(BinaryWriter bamlBinaryWriter) { // Remember the file location of this baml record. This // is needed if we have to come back later to update the [....] mode. if (FilePos == -1 && bamlBinaryWriter != null) { FilePos = bamlBinaryWriter.Seek(0,SeekOrigin.Current); } base.Write(bamlBinaryWriter); } // Adjust seeks pointer to this Record and updates the data. // Then sets seek pointer pack to original. // NOTE: This will ONLY work for file sizes under 2 gig. This is // not a problem for current useage, since this is mostly used // when updating LoadAsync attribute on the DocumentStart record, // which is usually set on the first element in the xaml file. internal virtual void UpdateWrite(BinaryWriter bamlBinaryWriter) { // default implementation, class should override if // wants to optimize to only update dirty data. long currentPosiition = bamlBinaryWriter.Seek(0,SeekOrigin.Current); // seek to original record position. Debug.Assert(FilePos != -1,"UpdateWrite called but Write Never was"); // Note: This only works for files up to 2 gig in length. // This is not a new restriction, but it should be // fixed to work with larger files... bamlBinaryWriter.Seek((int)FilePos,SeekOrigin.Begin); Write(bamlBinaryWriter); bamlBinaryWriter.Seek( (int) currentPosiition,SeekOrigin.Begin); } #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { LoadAsync = bamlBinaryReader.ReadBoolean(); MaxAsyncRecords = bamlBinaryReader.ReadInt32(); DebugBaml = bamlBinaryReader.ReadBoolean(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(LoadAsync); bamlBinaryWriter.Write(MaxAsyncRecords); bamlBinaryWriter.Write(DebugBaml); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlDocumentStartRecord newRecord = (BamlDocumentStartRecord)record; newRecord._maxAsyncRecords = _maxAsyncRecords; newRecord._loadAsync = _loadAsync; newRecord._filePos = _filePos; newRecord._debugBaml = _debugBaml; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.DocumentStart; } } internal bool LoadAsync { get { return _loadAsync; } #if !PBTCOMPILER set { _loadAsync = value; } #endif } internal int MaxAsyncRecords { get { return _maxAsyncRecords; } set { _maxAsyncRecords = value; } } // Position in the baml file stream internal long FilePos { get { return _filePos; } set { _filePos = value; } } // Are there Debug Baml Records in this Baml Stream internal bool DebugBaml { get { return _debugBaml; } set { _debugBaml = value; } } #endregion Properties #region Data int _maxAsyncRecords = -1; bool _loadAsync = false; long _filePos = -1; bool _debugBaml = false; #endregion Data } // This marks the end tag of an element //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlElementEndRecord : BamlRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.ElementEnd; } } #endregion Properties } // This marks the start tag of an element being used as the key for an IDictionary internal class BamlKeyElementStartRecord : BamlDefAttributeKeyTypeRecord, IBamlDictionaryKey { internal BamlKeyElementStartRecord() { Pin(); // Don't allow this record to be recycled in the read cache. } #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.KeyElementStart; } } #endregion Properties } // This marks the end tag of an element being used as the key for an IDictionary internal class BamlKeyElementEndRecord : BamlElementEndRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.KeyElementEnd; } } #endregion Properties } // This marks the end of the baml stream, or document. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlDocumentEndRecord : BamlRecord { #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.DocumentEnd; } } #endregion Properties } // The following records are used internally in the baml stream to // define attribute (eg - property), type and assembly information // for records that follow later on in the stream. They are never // publically exposed // Information about an assembly where a type is defined //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlAssemblyInfoRecord : BamlVariableSizedRecord { internal BamlAssemblyInfoRecord() { Pin(); // Don't allow this record to be recycled in the read cache. AssemblyId = -1; } #region Methods #if !PBTCOMPILER // LoadRecord specific data internal override void LoadRecordData(BinaryReader bamlBinaryReader) { AssemblyId = bamlBinaryReader.ReadInt16(); AssemblyFullName = bamlBinaryReader.ReadString(); } #endif // write record specific Data. internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { // write out an int for record size but we'll go back and fill bamlBinaryWriter.Write(AssemblyId); bamlBinaryWriter.Write(AssemblyFullName); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlAssemblyInfoRecord newRecord = (BamlAssemblyInfoRecord)record; newRecord._assemblyFullName = _assemblyFullName; newRecord._assembly = _assembly; } #endif #endregion Methods #region Properties // The following are stored in the baml stream // ID of this assembly internal short AssemblyId { get { short value = (short) _flags[_assemblyIdLowSection]; value |= (short) (_flags[_assemblyIdHighSection] << 8); return value; } set { _flags[_assemblyIdLowSection] = (short) (value & 0xff); _flags[_assemblyIdHighSection] = (short) ((value & 0xff00) >> 8); } } // Allocate space in _flags. // BitVector32 doesn't support 16 bit sections, so we have to break // it up into 2 sections. private static BitVector32.Section _assemblyIdLowSection = BitVector32.CreateSection( (short)0xff, BamlVariableSizedRecord.LastFlagsSection ); private static BitVector32.Section _assemblyIdHighSection = BitVector32.CreateSection( (short)0xff, _assemblyIdLowSection ); #if !PBTCOMPILER // This provides subclasses with a referece section to create their own section. internal new static BitVector32.Section LastFlagsSection { get { return _assemblyIdHighSection; } } #endif // Full name of this assembly, excluding any suffix. This has // the format "AssemblyName, Version, Culture, PublicKeyToken" when we // have a true full name. Sometimes we aren't given the full assembly // name, in which case the full name is the same as the short name. internal string AssemblyFullName { get { return _assemblyFullName; } set { _assemblyFullName = value; } } // The following are not part of the BAML stream // Identify type of record internal override BamlRecordType RecordType { get { return BamlRecordType.AssemblyInfo; } } // The actual loaded assembly internal Assembly Assembly { get { return _assembly; } set { _assembly = value; } } #endregion Properties #region Data string _assemblyFullName; Assembly _assembly; #endregion Data } // Information about a type for an element, object or property //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlTypeInfoRecord : BamlVariableSizedRecord { internal BamlTypeInfoRecord() { Pin(); // Don't allow this record to be recycled in the read cache. TypeId = -1; } #region Methods #if !PBTCOMPILER // LoadRecord specific data internal override void LoadRecordData(BinaryReader bamlBinaryReader) { TypeId = bamlBinaryReader.ReadInt16(); AssemblyId = bamlBinaryReader.ReadInt16(); TypeFullName = bamlBinaryReader.ReadString(); // Note that the upper 4 bits of the AssemblyId are used for flags _typeInfoFlags = (TypeInfoFlags)(AssemblyId >> 12); _assemblyId &= 0x0FFF; } #endif // write record specific Data. internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { // write out an int for record size but we'll go back and fill bamlBinaryWriter.Write(TypeId); // Note that the upper 4 bits of the AssemblyId are used for flags bamlBinaryWriter.Write((short)(((ushort)AssemblyId) | (((ushort)_typeInfoFlags) << 12))); bamlBinaryWriter.Write(TypeFullName); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlTypeInfoRecord newRecord = (BamlTypeInfoRecord)record; newRecord._typeInfoFlags = _typeInfoFlags; newRecord._assemblyId = _assemblyId; newRecord._typeFullName = _typeFullName; newRecord._type = _type; } #endif #endregion Methods #region Properties // The following are stored in the baml stream // ID of this type. Refenced in other baml records where a // Type is needed. internal short TypeId { get { short value = (short) _flags[_typeIdLowSection]; value |= (short) (_flags[_typeIdHighSection] << 8); return value; } set { _flags[_typeIdLowSection] = (short) (value & 0xff); _flags[_typeIdHighSection] = (short) ((value & 0xff00) >> 8); } } // Assembly id of the assembly where this type is defined. // NOTE: This is always positive in BAML files, but can be set // to -1 for known types when created programmatically. internal short AssemblyId { get { return _assemblyId; } set { // Make sure we don't intrude on the Flags portion of the assembly ID if (_assemblyId > 0x0FFF) { throw new XamlParseException(SR.Get(SRID.ParserTooManyAssemblies)); } _assemblyId = value; } } // Fully qualified name of type, including namespace internal string TypeFullName { get { return _typeFullName; } set { _typeFullName = value; } } // Additional properties not stored in the baml stream internal override BamlRecordType RecordType { get { return BamlRecordType.TypeInfo; } } #if !PBTCOMPILER // Actual type. Filled in here when xaml is used to create // a tree, and the token reader knows the type internal Type Type { get { return _type; } set { _type = value; } } // Extract the namespace from the type full name and return // it. We are assuming here that the type full name has a single // classname at the end and we are not refering to a nested class... internal string ClrNamespace { get { int periodIndex = _typeFullName.LastIndexOf('.'); return periodIndex > 0 ? _typeFullName.Substring(0, periodIndex) : string.Empty; } } #endif // True if there is a serializer associated with this type internal virtual bool HasSerializer { get { return false; } } internal bool IsInternalType { #if !PBTCOMPILER get { return ((_typeInfoFlags & TypeInfoFlags.Internal) == TypeInfoFlags.Internal); } #endif set { // Don't allow resetting to false (i.e. converting back top public if // it becomes non-public, for added safety. if (value) { _typeInfoFlags |= TypeInfoFlags.Internal; } } } #endregion Properties #region Data // Allocate space in _flags. // BitVector32 doesn't support 16 bit sections, so we have to break // it up into 2 sections. private static BitVector32.Section _typeIdLowSection = BitVector32.CreateSection( (short)0xff, BamlVariableSizedRecord.LastFlagsSection ); private static BitVector32.Section _typeIdHighSection = BitVector32.CreateSection( (short)0xff, _typeIdLowSection ); #if !PBTCOMPILER // This provides subclasses with a referece section to create their own section. internal new static BitVector32.Section LastFlagsSection { get { return _typeIdHighSection; } } #endif // Flags contained in TypeInfo that give additional information // about the type that is determined at compile time. [Flags] private enum TypeInfoFlags : byte { Internal = 0x1, UnusedTwo = 0x2, UnusedThree = 0x4, } TypeInfoFlags _typeInfoFlags = 0; short _assemblyId = -1; string _typeFullName; #if !PBTCOMPILER Type _type; #endif #endregion Data } // Type info record for a type that has a custom serializer associated with it. // This gives the serializer type that will be used when deserializing this type //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlTypeInfoWithSerializerRecord : BamlTypeInfoRecord { internal BamlTypeInfoWithSerializerRecord() { Pin(); // Don't allow this record to be recycled in the read cache. } #region Methods #if !PBTCOMPILER // LoadRecord specific data internal override void LoadRecordData(BinaryReader bamlBinaryReader) { base.LoadRecordData(bamlBinaryReader); SerializerTypeId = bamlBinaryReader.ReadInt16(); } #endif // write record specific Data. internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { base.WriteRecordData(bamlBinaryWriter); bamlBinaryWriter.Write(SerializerTypeId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlTypeInfoWithSerializerRecord newRecord = (BamlTypeInfoWithSerializerRecord)record; newRecord._serializerTypeId = _serializerTypeId; newRecord._serializerType = _serializerType; } #endif #endregion Methods #region Properties // The following are stored in the baml stream // ID of this type. Refenced in other baml records where a // Type is needed. internal short SerializerTypeId { get { return _serializerTypeId; } set { _serializerTypeId = value; } } // Additional properties not stored in the baml stream internal override BamlRecordType RecordType { get { return BamlRecordType.TypeSerializerInfo; } } #if !PBTCOMPILER // Actual type of associated serializer. Filled in here when xaml is used to create // a tree, and the token reader knows the type of the serializer, or // when we are reading the baml file and have determined the // serializer type. internal Type SerializerType { get { return _serializerType; } set { _serializerType = value; } } #endif // True if there is a serializer associated with this type. A serializer // will never be the first type object in a baml file, so its type ID will // never be 0. Any other ID indicates we have a serializer. internal override bool HasSerializer { get { Debug.Assert( SerializerTypeId != 0 ); return true; } } #endregion Properties #region Data short _serializerTypeId = 0; #if !PBTCOMPILER Type _serializerType; #endif #endregion Data } // Used for mapping properties and events to an owner type, given the // name of the attribute. Note that Attribute is used for historical // reasons and for similarities to Xml attributes. For us attributes // are just properties and events. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlAttributeInfoRecord : BamlVariableSizedRecord { internal BamlAttributeInfoRecord() { Pin(); // Don't allow this record to be recycled in the read cache. AttributeUsage = BamlAttributeUsage.Default; } #region Methods #if !PBTCOMPILER // LoadRecord specific data internal override void LoadRecordData(BinaryReader bamlBinaryReader) { AttributeId = bamlBinaryReader.ReadInt16(); OwnerTypeId = bamlBinaryReader.ReadInt16(); AttributeUsage = (BamlAttributeUsage)bamlBinaryReader.ReadByte(); Name = bamlBinaryReader.ReadString(); } #endif // write record specific Data. internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { // write out an int for record size but we'll go back and fill bamlBinaryWriter.Write(AttributeId); bamlBinaryWriter.Write(OwnerTypeId); bamlBinaryWriter.Write((Byte)AttributeUsage); bamlBinaryWriter.Write(Name); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlAttributeInfoRecord newRecord = (BamlAttributeInfoRecord)record; newRecord._ownerId = _ownerId; newRecord._attributeId = _attributeId; newRecord._name = _name; newRecord._ownerType = _ownerType; newRecord._Event = _Event; newRecord._dp = _dp; newRecord._ei = _ei; newRecord._pi = _pi; newRecord._smi = _smi; newRecord._gmi = _gmi; newRecord._dpOrMiOrPi = _dpOrMiOrPi; } #endif #endregion Methods #region Properties // The following 3 properties are stored in the Baml file and are read and // written by the BamlRecordReader and BamlXamlNodeWriter internal short OwnerTypeId { get { return _ownerId; } set { _ownerId = value; } } internal short AttributeId { set { _attributeId = value; } get { return _attributeId; } } internal string Name { get { return _name; } set { _name = value; } } // The following properties are derived at runtime from the above 3 properties using // the Mapper. Which are set depends on the attribute and the context in which it is // used. internal override BamlRecordType RecordType { get { return BamlRecordType.AttributeInfo; } } #if !PBTCOMPILER // Return type of property. Note that this uses the same logic as // Mapper.GetPropertyType but uses the cached values of DP, PropInfo // and AttachedPropertySetter. internal Type GetPropertyType() { Type validType = null; DependencyProperty dp = DP; if (dp == null) { MethodInfo methodInfo = AttachedPropertySetter; if (methodInfo == null) { PropertyInfo propInfo = PropInfo; validType = propInfo.PropertyType; } else { ParameterInfo[] paramInfo = methodInfo.GetParameters(); validType = paramInfo[1].ParameterType; } } else { validType = dp.PropertyType; } return validType; } #endif ////// Set the PropertyMember, which can is assumed to be a MethodInfo for /// the static setter method for a DP or a PropertyInfo for the clr property /// ////// The possibility of having multiple member info cached for an attribute is when a /// dependency property that does not belong to the default namespace is used in once /// in a once with a namespace prefix and once without it. When it has a namespace /// prefix we correctly find the dependency property for it. However when it does not /// have a namespace prefix it the parser tries to look it up in the default namespace /// and falls back to using the clr wrapper's property info for it instead. Another /// scenario that requires caching more than one property info is when a dependency /// property has both a static settor and a clr wrapper. /// internal void SetPropertyMember (object propertyMember) { Debug.Assert((propertyMember is MethodInfo) || (propertyMember is PropertyInfo) || (KnownTypes.Types[(int)KnownElements.DependencyProperty].IsAssignableFrom(propertyMember.GetType())), "Cache can hold either a MethodInfo and/or a PropertyInfo and/or a DependencyProperty for a given attribute"); if (PropertyMember == null) { PropertyMember = propertyMember; } else { // Cache a additional MemberInfo for the given attribute object[] arr = PropertyMember as object[]; if (arr == null) { arr = new object[3]; arr[0] = PropertyMember; arr[1] = propertyMember; } else { Debug.Assert(arr.Length == 3 && arr[0] != null && arr[1] != null); arr[2] = propertyMember; } } } ////// Return the PropertyMember, which can is assumed to be a MethodInfo for /// the static setter method for a DP or a PropertyInfo for the clr property /// ////// The possibility of having multiple member info cached for an attribute is when a /// dependency property that does not belong to the default namespace is used in once /// in a once with a namespace prefix and once without it. When it has a namespace /// prefix we correctly find the dependency property for it. However when it does not /// have a namespace prefix it the parser tries to look it up in the default namespace /// and falls back to using the clr wrapper's property info for it instead. Another /// scenario that requires caching more than one property info is when a dependency /// property has both a static settor and a clr wrapper. /// internal object GetPropertyMember(bool onlyPropInfo) { if (PropertyMember == null || PropertyMember is MemberInfo || KnownTypes.Types[(int)KnownElements.DependencyProperty].IsAssignableFrom(PropertyMember.GetType( )) ) { if (onlyPropInfo) { #if PBTCOMPILER return PropertyMember as PropertyInfo; #else return PropInfo; #endif } else { return PropertyMember; } } else { // The attribute has multiple member info. Choose which one to return. object[] arr = (object[])PropertyMember; Debug.Assert(arr.Length == 3 && arr[0] != null && arr[1] != null); // If someone queries any MemberInfo for the given attribute then we return the // first member info cached for it. If they are looking specifically for a // PropertyInfo we try and find them one. if (onlyPropInfo) { if (arr[0] is PropertyInfo) { return (PropertyInfo)arr[0]; } else if (arr[1] is PropertyInfo) { return (PropertyInfo)arr[1]; } else { return arr[2] as PropertyInfo; } } else { return arr[0]; } } } // Cached value of the DependencyProperty, MethodInfo for the static setter // method, or the PropertyInfo for a given property. If this is an // event, then this is null. internal object PropertyMember { get { return _dpOrMiOrPi; } set { _dpOrMiOrPi = value; } } #if !PBTCOMPILER // The cached type of the owner or declarer of this property internal Type OwnerType { get { return _ownerType; } set { _ownerType = value; } } // Cached value of the routed event id, if this attribute is for a // routed event. If not a routed event, this is null. internal RoutedEvent Event { get { return _Event; } set { _Event = value; } } // Cached value of DP, if available internal DependencyProperty DP { get { if (null != _dp) return _dp; else return _dpOrMiOrPi as DependencyProperty; } set { _dp = value; if (_dp != null) { // Release the other copy of the string _name = _dp.Name; } } } // Cached value of static property setter method info, if available internal MethodInfo AttachedPropertySetter { get { return _smi; } set { _smi = value; } } // Cached value of static property getter method info, if available internal MethodInfo AttachedPropertyGetter { get { return _gmi; } set { _gmi = value; } } // Cached value of EventInfo, if available internal EventInfo EventInfo { get { return _ei; } set { _ei = value; } } // Cached value of PropertyInfo, if available internal PropertyInfo PropInfo { get { return _pi; } set { _pi = value; } } internal bool IsInternal { get { return _flags[_isInternalSection] == 1 ? true : false; } set { _flags[_isInternalSection] = value ? 1 : 0; } } #endif // Some attributes have special usage, such as setting the XmlLang and XmlSpace // strings in the parser context. This is flagged with this property internal BamlAttributeUsage AttributeUsage { get { return (BamlAttributeUsage) _flags[_attributeUsageSection]; } set { _flags[_attributeUsageSection] = (int) value; } } // Allocate space in _flags. private static BitVector32.Section _isInternalSection = BitVector32.CreateSection( 1, BamlVariableSizedRecord.LastFlagsSection ); private static BitVector32.Section _attributeUsageSection = BitVector32.CreateSection( 3, _isInternalSection ); #if !PBTCOMPILER // This provides subclasses with a referece section to create their own section. internal new static BitVector32.Section LastFlagsSection { get { return _attributeUsageSection; } } #endif #endregion Properties #if !PBTCOMPILER public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0} owner={1} attr({2}) is '{3}'", RecordType, GetTypeName(OwnerTypeId), AttributeId, _name); } #endif #region Data short _ownerId; short _attributeId; string _name; #if !PBTCOMPILER Type _ownerType = null; RoutedEvent _Event = null; DependencyProperty _dp = null; EventInfo _ei = null; PropertyInfo _pi = null; MethodInfo _smi = null; MethodInfo _gmi = null; #endif object _dpOrMiOrPi = null; // MethodInfo, PropertyInfo or DependencyProperty #endregion Data } // Information about a String that is an entry in the String table. //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlStringInfoRecord : BamlVariableSizedRecord { internal BamlStringInfoRecord() { Pin(); // Don't allow this record to be recycled in the read cache. StringId = -1; } #region Methods #if !PBTCOMPILER // LoadRecord specific data internal override void LoadRecordData(BinaryReader bamlBinaryReader) { StringId = bamlBinaryReader.ReadInt16(); Value = bamlBinaryReader.ReadString(); } #endif // write record specific Data. internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { // write out an int for string Id bamlBinaryWriter.Write(StringId); bamlBinaryWriter.Write(Value); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlStringInfoRecord newRecord = (BamlStringInfoRecord)record; newRecord._value = _value; } #endif #endregion Methods #region Properties // Resource Identifier pointing to the StringTable Entry internal short StringId { get { short value = (short) _flags[_stringIdLowSection]; value |= (short) (_flags[_stringIdHighSection] << 8); return value; } set { _flags[_stringIdLowSection] = (short) (value & 0xff); _flags[_stringIdHighSection] = (short) ((value & 0xff00) >> 8); } } // Resource String internal string Value { get { return _value; } set { _value = value; } } // Additional properties not stored in the baml stream internal override BamlRecordType RecordType { get { return BamlRecordType.StringInfo; } } // True if there is a serializer associated with this type internal virtual bool HasSerializer { get { return false; } } #endregion Properties #if !PBTCOMPILER public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0} stringId({1}='{2}'", RecordType, StringId, _value); } #endif #region Data // Allocate space in _flags. // BitVector32 doesn't support 16 bit sections, so we have to break // it up into 2 sections. private static BitVector32.Section _stringIdLowSection = BitVector32.CreateSection( (short)0xff, BamlVariableSizedRecord.LastFlagsSection ); private static BitVector32.Section _stringIdHighSection = BitVector32.CreateSection( (short)0xff, _stringIdLowSection ); #if !PBTCOMPILER // This provides subclasses with a referece section to create their own section. internal new static BitVector32.Section LastFlagsSection { get { return _stringIdHighSection; } } #endif string _value ; #endregion Data } // Sets the content property context for an element //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlContentPropertyRecord : BamlRecord { #region Methods #if !PBTCOMPILER // LoadRecord specific data internal override void LoadRecordData(BinaryReader bamlBinaryReader) { AttributeId = bamlBinaryReader.ReadInt16(); } #endif // write record specific Data. internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { // write out an int for attribute Id bamlBinaryWriter.Write(AttributeId); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlContentPropertyRecord newRecord = (BamlContentPropertyRecord)record; newRecord._attributeId = _attributeId; } #endif #endregion Methods #region Properties // Id of the property being set as the context internal short AttributeId { get { return _attributeId; } set { _attributeId = value; } } // Additional properties not stored in the baml stream internal override BamlRecordType RecordType { get { return BamlRecordType.ContentProperty; } } // True if there is a serializer associated with this type internal virtual bool HasSerializer { get { return false; } } #endregion Properties #region Data short _attributeId = -1; #endregion Data } // Debugging Linenumber record. Linenumber from the XAML //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlLineAndPositionRecord : BamlRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { LineNumber = (uint) bamlBinaryReader.ReadInt32(); LinePosition = (uint) bamlBinaryReader.ReadInt32(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(LineNumber); bamlBinaryWriter.Write(LinePosition); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlLineAndPositionRecord newRecord = (BamlLineAndPositionRecord)record; newRecord._lineNumber = _lineNumber; newRecord._linePosition = _linePosition; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.LineNumberAndPosition; } } // Id of the type of this object internal uint LineNumber { get { return _lineNumber; } set { _lineNumber = value; } } internal uint LinePosition { get { return _linePosition; } set { _linePosition = value; } } internal override Int32 RecordSize { get { return 8; } } uint _lineNumber; uint _linePosition; #endregion Properties #if !PBTCOMPILER public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0} LineNum={1} Pos={2}", RecordType, LineNumber, LinePosition); } #endif } // Debugging Line Position record. Line Position from the XAML //// This code should always be transparent. Meaning you should never add // SecurityCritical to this section of the code. // internal class BamlLinePositionRecord : BamlRecord { #region Methods #if !PBTCOMPILER internal override void LoadRecordData(BinaryReader bamlBinaryReader) { LinePosition = (uint) bamlBinaryReader.ReadInt32(); } #endif internal override void WriteRecordData(BinaryWriter bamlBinaryWriter) { bamlBinaryWriter.Write(LinePosition); } #if !PBTCOMPILER internal override void Copy(BamlRecord record) { base.Copy(record); BamlLinePositionRecord newRecord = (BamlLinePositionRecord)record; newRecord._linePosition = _linePosition; } #endif #endregion Methods #region Properties internal override BamlRecordType RecordType { get { return BamlRecordType.LinePosition; } } internal uint LinePosition { get { return _linePosition; } set { _linePosition = value; } } internal override Int32 RecordSize { get { return 4; } } uint _linePosition; #endregion Properties #if !PBTCOMPILER public override string ToString() { return string.Format(CultureInfo.InvariantCulture, "{0} LinePos={1}", RecordType, LinePosition); } #endif } } // 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
- Configuration.cs
- CodeSnippetExpression.cs
- WithStatement.cs
- XamlStream.cs
- ConfigurationValue.cs
- Tuple.cs
- ObjectFactoryCodeDomTreeGenerator.cs
- ObjectDataSourceMethodEventArgs.cs
- TextBlock.cs
- SQLInt32.cs
- SafeTimerHandle.cs
- StorageEndPropertyMapping.cs
- TextTreeDeleteContentUndoUnit.cs
- FlagsAttribute.cs
- _LazyAsyncResult.cs
- DataGridViewHitTestInfo.cs
- RefreshPropertiesAttribute.cs
- BasicExpandProvider.cs
- COAUTHIDENTITY.cs
- HandlerMappingMemo.cs
- ResourceExpression.cs
- DataStorage.cs
- LineGeometry.cs
- OleDbError.cs
- SymbolUsageManager.cs
- VectorAnimation.cs
- GridViewDeletedEventArgs.cs
- StringFunctions.cs
- SchemaCollectionCompiler.cs
- LineGeometry.cs
- ObjectTag.cs
- ResourceDisplayNameAttribute.cs
- DeviceFiltersSection.cs
- MultiAsyncResult.cs
- FollowerQueueCreator.cs
- MessageQueuePermission.cs
- CryptoProvider.cs
- AnnotationHighlightLayer.cs
- SqlNodeTypeOperators.cs
- HtmlTernaryTree.cs
- RoutedEventConverter.cs
- ISAPIRuntime.cs
- GradientStopCollection.cs
- BindingSource.cs
- HelpProvider.cs
- SuppressedPackageProperties.cs
- DateTimeFormat.cs
- XhtmlBasicLiteralTextAdapter.cs
- DataStorage.cs
- QilFactory.cs
- SigningCredentials.cs
- Helpers.cs
- InputLanguage.cs
- Bits.cs
- DataGridItem.cs
- IntegrationExceptionEventArgs.cs
- XmlDataImplementation.cs
- EdgeModeValidation.cs
- UpdateCommand.cs
- SQLDateTimeStorage.cs
- XmlSchemaSet.cs
- ImageListStreamer.cs
- WinFormsSpinner.cs
- DesignerOptionService.cs
- InputBuffer.cs
- TypeHelpers.cs
- AsyncOperation.cs
- PropertyItem.cs
- SerialStream.cs
- BaseTemplateParser.cs
- FormViewModeEventArgs.cs
- System.Data.OracleClient_BID.cs
- SplineKeyFrames.cs
- QueryOperationResponseOfT.cs
- AuthenticationModulesSection.cs
- AnnotationStore.cs
- ConfigPathUtility.cs
- SignatureToken.cs
- StrokeFIndices.cs
- SqlUserDefinedAggregateAttribute.cs
- LabelDesigner.cs
- CookieHandler.cs
- ResourceKey.cs
- IisTraceListener.cs
- sortedlist.cs
- CounterCreationDataCollection.cs
- OleDbPermission.cs
- CodeRemoveEventStatement.cs
- BaseProcessor.cs
- TextElementCollection.cs
- DbConnectionPoolGroup.cs
- _NestedSingleAsyncResult.cs
- Row.cs
- MSAAWinEventWrap.cs
- DesignerRegionMouseEventArgs.cs
- Point3DAnimation.cs
- DesignerResources.cs
- CompModSwitches.cs
- CombinedTcpChannel.cs
- ISessionStateStore.cs