Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Markup / BamlReader.cs / 1305600 / BamlReader.cs
/****************************************************************************\
*
* File: BamlReader.cs
*
* Purpose: Public interface for reading BamlRecords with an interface
* that is similar to XmlReader
*
* History:
* 10/09/2003 peterost - created
*
* Copyright (C) 2003 by Microsoft Corporation. All rights reserved.
*
\***************************************************************************/
using System;
using System.Xml;
using System.IO;
using System.Windows;
using System.Windows.Navigation;
using System.Text;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;
using System.Windows.Threading;
using System.Globalization;
using MS.Utility;
using MS.Internal;
namespace System.Windows.Markup
{
///
/// Type of BAML node at the current BamlReader location in
/// the BAML stream.
///
internal enum BamlNodeType
{
///
/// This is returned if Read() has not been called, or the end of the
/// file has been reached.
///
None,
///
/// Start of a BAML document. This contains version information about the BAML.
///
StartDocument,
///
/// End of a BAML document
///
EndDocument,
///
/// Connection Id.
///
ConnectionId,
///
/// Start of an Element. An Element is any object that exists in
/// an object tree. This has a rough correspondance to Element nodes in XML
///
StartElement,
///
/// End of an Element.
///
EndElement,
///
/// A simple property of an Element. This can be a native property, attached
/// property, or XML specific properties such as namespaces
///
Property,
///
/// The content property of an Element.
///
ContentProperty,
///
/// A namespace property that defines prefix to namespace mappings in xml
///
XmlnsProperty,
///
/// The start of a compound property on an Element. This is used when the property value is
/// represented as a single string Value, but as an element tree.
///
StartComplexProperty,
///
/// The end of a compound property on an Element.
///
EndComplexProperty,
///
/// A section of literal content that is handled by an object
///
LiteralContent,
///
/// Text content of an element.
///
Text,
///
/// A RoutedEvent
///
RoutedEvent,
///
/// A non-routed, or normal CLR Event
///
Event,
///
/// A reference to a Resource that is included at this point in the BAML stream
///
IncludeReference,
///
/// A specific attribute or property in the reserved "Definition" namespace.
/// These attributes do not map to CLR properties or events, but are used
/// as processing directives.
///
DefAttribute,
///
/// A specific attribute or property in the reserved "PresentationOptions" namespace.
/// These attributes do not map to CLR properties or events, but are used
/// as processing directives.
///
PresentationOptionsAttribute,
///
/// A namespace mapping instruction used for including custom code and namespaces
///
PIMapping,
///
/// Start of a section that specifies a list of objects to be passed to the
/// element's constructor
///
StartConstructor,
///
/// End of a section that specifies a list of objects to be passed to the
/// element's constructor
///
EndConstructor
}
///
/// Reads BAML from a Stream and exposes an XmlReader-liker interface for BAML
///
//
// This code should always be transparent. Meaning you should never add
// SecurityCritical to this section of the code.
//
internal class BamlReader
{
#region Constructor
///
/// Create an instance of the BamlReader on the passed stream using
/// the passed ParserContext.
/// summary>
public BamlReader(Stream bamlStream)
{
_parserContext = new ParserContext();
_parserContext.XamlTypeMapper = XmlParserDefaults.DefaultMapper;
_bamlRecordReader = new BamlRecordReader(bamlStream, _parserContext, false);
_readState = ReadState.Initial;
_bamlNodeType = BamlNodeType.None;
_prefixDictionary = new XmlnsDictionary();
_value = string.Empty;
_assemblyName = string.Empty;
_prefix = string.Empty;
_xmlNamespace = string.Empty;
_clrNamespace = string.Empty;
_name = string.Empty;
_localName = string.Empty;
_ownerTypeName = string.Empty;
_properties = new ArrayList();
_haveUnprocessedRecord = false;
_deferableContentBlockDepth = -1;
_nodeStack = new Stack();
_reverseXmlnsTable = new Dictionary>();
}
#endregion Constructor
#region Public Methods
///
/// Return the number of properties. Note that this
/// does not include complex properties or children elements
///
public int PropertyCount
{
get { return _properties.Count; }
}
///
/// Return true if the current node has any simple properties
///
public bool HasProperties
{
get { return PropertyCount > 0; }
}
///
/// Return the connection Id of current element for hooking up
/// IDs and events.
///
public Int32 ConnectionId
{
get { return _connectionId; }
}
///
/// Defines what this attribute is used for such as being an alias for
/// xml:lang, xml:space or x:ID
///
public BamlAttributeUsage AttributeUsage
{
get { return _attributeUsage; }
}
///
/// Gets the type of the current node (eg Element, StartComplexProperty,
/// Text, etc)
///
public BamlNodeType NodeType
{
get { return _bamlNodeType; }
}
///
/// Gets the fully qualified name of the current node.
///
public string Name
{
get { return _name; }
}
///
/// Gets the local name only, with prefix and owning class removed
///
public string LocalName
{
get { return _localName; }
}
///
/// Gets the prefix associated with the current node, if there is one
///
//
// NOTE: Used by the localization tools via reflection.
//
public string Prefix
{
get { return _prefix; }
}
///
/// Gets the assembly name associated with the type of the current node, if there is one
///
public string AssemblyName
{
get { return _assemblyName; }
}
///
/// Gets the XML namespace URI of the node on which the reader is positioned
///
public string XmlNamespace
{
get { return _xmlNamespace; }
}
///
/// Gets the CLR namespace of the node on which the reader is positioned
///
public string ClrNamespace
{
get { return _clrNamespace; }
}
///
/// Gets the text value of the current node (eg property value or text content)
///
public string Value
{
get { return _value; }
}
public bool IsInjected
{
get { return _isInjected; }
}
// Whether this object instance is expected to be created via TypeConverter
public bool CreateUsingTypeConverter
{
get { return _useTypeConverter; }
}
public string TypeConverterName
{
get { return _typeConverterName; }
}
public string TypeConverterAssemblyName
{
get { return _typeConverterAssemblyName; }
}
///
/// Reads the next node from the stream.
///
public bool Read()
{
if (_readState == ReadState.EndOfFile ||
_readState == ReadState.Closed)
{
throw new InvalidOperationException(SR.Get(SRID.BamlReaderClosed));
}
ReadNextRecord();
return _readState != ReadState.EndOfFile;
}
private BamlNodeType NodeTypeInternal
{
set { _bamlNodeType = value; }
}
private void AddToPropertyInfoCollection(object info)
{
_properties.Add(info);
}
///
/// Close the underlying BAML stream.
///
///
/// Once the BamlReader is closed, it cannot be used
/// for any further operations. Calling any public interfaces will fail.
///
public void Close()
{
if (_readState != ReadState.Closed)
{
_bamlRecordReader.Close();
_currentBamlRecord = null;
_bamlRecordReader = null;
_readState = ReadState.Closed;
}
}
///
/// Moves to the first property for this element or object.
/// Return true if property exists, false otherwise.
///
public bool MoveToFirstProperty()
{
if (HasProperties)
{
_propertiesIndex = -1;
return MoveToNextProperty();
}
else
{
return false;
}
}
///
/// Move to the next property for this element or object.
/// Return true if there is a next property; false if there are no more properties.
///
public bool MoveToNextProperty()
{
if (_propertiesIndex < _properties.Count - 1)
{
_propertiesIndex++;
object obj = _properties[_propertiesIndex];
BamlPropertyInfo info = obj as BamlPropertyInfo;
if (info != null)
{
_name = info.Name;
_localName = info.LocalName;
int index = info.Name.LastIndexOf(".", StringComparison.Ordinal);
if (index > 0)
{
_ownerTypeName = info.Name.Substring(0, index);
}
else
{
// Eg. xmlns property
_ownerTypeName = string.Empty;
}
_value = info.Value;
_assemblyName = info.AssemblyName;
_prefix = info.Prefix;
_xmlNamespace = info.XmlNamespace;
_clrNamespace = info.ClrNamespace;
_connectionId = 0;
_contentPropertyName = string.Empty;
_attributeUsage = info.AttributeUsage;
// There are several node types for properties, but for now the only one that
// doesn't map to BamlNodeType.Property is xml namespace declarations.
if (info.RecordType == BamlRecordType.XmlnsProperty)
{
NodeTypeInternal = BamlNodeType.XmlnsProperty;
}
else if (info.RecordType == BamlRecordType.DefAttribute)
{
NodeTypeInternal = BamlNodeType.DefAttribute;
}
else if (info.RecordType == BamlRecordType.PresentationOptionsAttribute)
{
NodeTypeInternal = BamlNodeType.PresentationOptionsAttribute;
}
else
{
NodeTypeInternal = BamlNodeType.Property;
}
return true;
}
BamlContentPropertyInfo cpInfo = obj as BamlContentPropertyInfo;
if(null != cpInfo)
{
_contentPropertyName = cpInfo.LocalName;
_connectionId = 0;
_prefix = string.Empty;
_name = cpInfo.Name;
int index = cpInfo.Name.LastIndexOf(".", StringComparison.Ordinal);
if (index > 0)
{
_ownerTypeName = cpInfo.Name.Substring(0, index);
}
_localName = cpInfo.LocalName;
_ownerTypeName = string.Empty;
_assemblyName = cpInfo.AssemblyName;
_xmlNamespace = string.Empty;
_clrNamespace = string.Empty;
_attributeUsage = BamlAttributeUsage.Default;
_value = cpInfo.LocalName;
NodeTypeInternal = BamlNodeType.ContentProperty;
return true;
}
// Otherwise it must be a ConnectionId.
// Is there something we can Assert on for that?
_connectionId = (Int32)obj;
_contentPropertyName = string.Empty;
_prefix = string.Empty;
_name = string.Empty;
_localName = string.Empty;
_ownerTypeName = string.Empty;
_assemblyName = string.Empty;
_xmlNamespace = string.Empty;
_clrNamespace = string.Empty;
_attributeUsage = BamlAttributeUsage.Default;
_value = _connectionId.ToString(CultureInfo.CurrentCulture);
NodeTypeInternal = BamlNodeType.ConnectionId;
return true;
}
else
{
return false;
}
}
#endregion Public Methods
#region Internal Methods
///
/// Gets the next BamlRecord to be processed
///
private void GetNextRecord()
{
if (_currentStaticResourceRecords != null)
{
// Load the record from the front loaded static resource
_currentBamlRecord = _currentStaticResourceRecords[_currentStaticResourceRecordIndex++];
if (_currentStaticResourceRecordIndex == _currentStaticResourceRecords.Count)
{
// We are done with the records for this front loaded static resource
_currentStaticResourceRecords = null;
_currentStaticResourceRecordIndex = -1;
}
}
else
{
// Use the BamlRecord Reader to get the record
_currentBamlRecord = _bamlRecordReader.GetNextRecord();
}
}
/***************************************************************************\
*
* BamlReader.ReadNextRecord
*
* Read the next record, setting the ReadState, NodeType and other pertinent
* information about the record just read.
*
\***************************************************************************/
private void ReadNextRecord()
{
// If this is the first call to Read. Then read the Version Header.
if(_readState == ReadState.Initial)
{
_bamlRecordReader.ReadVersionHeader();
}
// We'll read in a loop until we get to a significant record. Note that Assembly,
// Type and Attribute records are read and processed, but the BamlReader never stops
// on one of these records, since they are not externally exposed.
bool keepOnReading = true;
while (keepOnReading)
{
// We may already have a record that was previously read in but not
// processed. This occurs when we've looped through all the properties
// on an element and have encountered a non-property record to stop
// the loop. In that case don't read another record and just process
// the one we have.
if (_haveUnprocessedRecord)
{
_haveUnprocessedRecord = false;
}
else
{
GetNextRecord();
}
// If the current baml record is null, then the stream is finished, closed
// or something else that prevents us reading further, so treat this
// as an end-of-file condition
if (_currentBamlRecord == null)
{
NodeTypeInternal = BamlNodeType.None;
_readState = ReadState.EndOfFile;
ClearProperties();
return;
}
// By default, the read state is interactive after a record has been read, and we
// should stop reading after this record is processed. This may be altered for
// specific record types.
_readState = ReadState.Interactive;
keepOnReading = false;
switch (_currentBamlRecord.RecordType)
{
// The following three records are internal to the BAMLReader and
// are not exposed publicly. They are used to update the map table
// that maps ids to assemblies, types and attributes.
case BamlRecordType.AssemblyInfo:
ReadAssemblyInfoRecord();
keepOnReading = true;
break;
case BamlRecordType.TypeInfo:
case BamlRecordType.TypeSerializerInfo:
MapTable.LoadTypeInfoRecord((BamlTypeInfoRecord)_currentBamlRecord);
keepOnReading = true;
break;
case BamlRecordType.AttributeInfo:
MapTable.LoadAttributeInfoRecord((BamlAttributeInfoRecord)_currentBamlRecord);
keepOnReading = true;
break;
case BamlRecordType.StringInfo:
MapTable.LoadStringInfoRecord((BamlStringInfoRecord)_currentBamlRecord);
keepOnReading = true;
break;
case BamlRecordType.ContentProperty:
// This is just a cache of meta-data, no visible effect.
ReadContentPropertyRecord();
keepOnReading = true;
break;
// The following records are publically exposed
case BamlRecordType.DocumentStart:
ReadDocumentStartRecord();
break;
case BamlRecordType.DocumentEnd:
ReadDocumentEndRecord();
break;
case BamlRecordType.PIMapping:
ReadPIMappingRecord();
break;
case BamlRecordType.LiteralContent:
ReadLiteralContentRecord();
break;
case BamlRecordType.ElementStart:
case BamlRecordType.StaticResourceStart:
ReadElementStartRecord();
break;
case BamlRecordType.ElementEnd:
case BamlRecordType.StaticResourceEnd:
ReadElementEndRecord();
break;
case BamlRecordType.PropertyComplexStart:
case BamlRecordType.PropertyArrayStart:
case BamlRecordType.PropertyIListStart:
case BamlRecordType.PropertyIDictionaryStart:
ReadPropertyComplexStartRecord();
break;
case BamlRecordType.PropertyComplexEnd:
case BamlRecordType.PropertyArrayEnd:
case BamlRecordType.PropertyIListEnd:
case BamlRecordType.PropertyIDictionaryEnd:
ReadPropertyComplexEndRecord();
break;
case BamlRecordType.Text:
case BamlRecordType.TextWithId:
case BamlRecordType.TextWithConverter:
ReadTextRecord();
break;
case BamlRecordType.DeferableContentStart:
ReadDeferableContentRecord();
keepOnReading = true;
break;
case BamlRecordType.ConstructorParametersStart:
ReadConstructorStart();
break;
case BamlRecordType.ConstructorParametersEnd:
ReadConstructorEnd();
break;
case BamlRecordType.ConnectionId:
ReadConnectionIdRecord();
break;
case BamlRecordType.StaticResourceId:
ReadStaticResourceId();
keepOnReading = true;
break;
default:
// Can't have any other type of record at this point.
throw new InvalidOperationException(SR.Get(SRID.ParserUnknownBaml,
((int)_currentBamlRecord.RecordType).ToString(CultureInfo.CurrentCulture)));
}
}
}
/***************************************************************************\
*
* BamlReader.ReadProperties
*
* This is called when an element start has been encountered (or something
* similar) and a number of properties may or may not follow. Read all the
* properties, storing them in the _properties arraylist. When a non-property
* record is encountered, stop, but store that record as the
* _currentBamlRecord.
*
\***************************************************************************/
private void ReadProperties()
{
// Keep reading records until we get one that is not processed
while (!_haveUnprocessedRecord)
{
GetNextRecord();
ProcessPropertyRecord();
}
}
/***************************************************************************\
*
* BamlReader.ProcessPropertyRecord
*
* This is called we assume we have a record that is an attribute in the start
* tag of an xml element. It is processed here. If we encounter something
* that is not a 'property', then set the _haveUnprocessedRecord flag.
*
\***************************************************************************/
private void ProcessPropertyRecord()
{
switch (_currentBamlRecord.RecordType)
{
// The following five records are internal to the BAMLReader and
// are not exposed publicly. They are used to update the map table
// that maps ids to assemblies, types and attributes.
case BamlRecordType.AssemblyInfo:
ReadAssemblyInfoRecord();
break;
case BamlRecordType.TypeInfo:
case BamlRecordType.TypeSerializerInfo:
MapTable.LoadTypeInfoRecord((BamlTypeInfoRecord)_currentBamlRecord);
break;
case BamlRecordType.AttributeInfo:
MapTable.LoadAttributeInfoRecord((BamlAttributeInfoRecord)_currentBamlRecord);
break;
case BamlRecordType.StringInfo:
MapTable.LoadStringInfoRecord((BamlStringInfoRecord)_currentBamlRecord);
break;
// The following records are property-like
case BamlRecordType.XmlnsProperty:
ReadXmlnsPropertyRecord();
break;
case BamlRecordType.ConnectionId:
ReadConnectionIdRecord();
break;
case BamlRecordType.Property:
case BamlRecordType.PropertyWithConverter:
ReadPropertyRecord();
break;
case BamlRecordType.ContentProperty:
// This is just a cache of meta-data, no visible effect.
ReadContentPropertyRecord();
break;
case BamlRecordType.PropertyStringReference:
ReadPropertyStringRecord();
break;
case BamlRecordType.PropertyTypeReference:
ReadPropertyTypeRecord();
break;
case BamlRecordType.PropertyWithExtension:
ReadPropertyWithExtensionRecord();
break;
case BamlRecordType.PropertyWithStaticResourceId:
ReadPropertyWithStaticResourceIdRecord();
break;
case BamlRecordType.PropertyCustom:
ReadPropertyCustomRecord();
break;
case BamlRecordType.DefAttribute:
ReadDefAttributeRecord();
break;
case BamlRecordType.PresentationOptionsAttribute:
ReadPresentationOptionsAttributeRecord();
break;
case BamlRecordType.DefAttributeKeyType:
ReadDefAttributeKeyTypeRecord();
break;
case BamlRecordType.RoutedEvent:
ReadRoutedEventRecord();
break;
case BamlRecordType.ClrEvent:
ReadClrEventRecord();
break;
case BamlRecordType.KeyElementStart:
{
// Process the subtree that is stored as part of a key tree and
// translate this back into a compact MarkupExtension string that
// is represented as a x:Key="something"
BamlKeyInfo info = ProcessKeyTree();
AddToPropertyInfoCollection(info);
}
break;
// Any other record types are not processed here
default:
_haveUnprocessedRecord = true;
break;
}
}
/****************************************************************************\
*
* BamlReader.ReadXmlnsPropertyRecord
*
* Read the namespace record and update the namespace dictionary with the
* key being the namespace prefix and the value being the namespace string.
* Note that Xmlns properties are not the same as regular properties, since
* prefix, xmlnamespace, clrnamespace and name have quite different meanings.
*
\***************************************************************************/
private void ReadXmlnsPropertyRecord()
{
BamlXmlnsPropertyRecord bamlRecord = (BamlXmlnsPropertyRecord)_currentBamlRecord;
_parserContext.XmlnsDictionary[bamlRecord.Prefix] = bamlRecord.XmlNamespace;
_prefixDictionary[bamlRecord.XmlNamespace] = bamlRecord.Prefix;
BamlPropertyInfo info = new BamlPropertyInfo();
info.Value = bamlRecord.XmlNamespace;
info.XmlNamespace = string.Empty;
info.ClrNamespace = string.Empty;
info.AssemblyName = string.Empty;
info.Prefix = "xmlns";
info.LocalName = bamlRecord.Prefix == null ? string.Empty : bamlRecord.Prefix;
info.Name = (bamlRecord.Prefix == null || bamlRecord.Prefix == string.Empty) ?
"xmlns" :
"xmlns:" + bamlRecord.Prefix;
info.RecordType = BamlRecordType.XmlnsProperty;
AddToPropertyInfoCollection(info);
}
/***************************************************************************\
*
* BamlReader.ReadPropertyRecord
*
* Read the property record and store the pertinent contents in the
* _properties array list.
*
\***************************************************************************/
private void ReadPropertyRecord()
{
string value = ((BamlPropertyRecord)_currentBamlRecord).Value;
// Escape the text as necessary to avoid being mistaken for a MarkupExtension.
value = MarkupExtensionParser.AddEscapeToLiteralString(value);
AddToPropertyInfoCollection(ReadPropertyRecordCore(value));
}
private void ReadContentPropertyRecord()
{
BamlContentPropertyInfo cpInfo = new BamlContentPropertyInfo();
BamlContentPropertyRecord bamlRecord = (BamlContentPropertyRecord)_currentBamlRecord;
SetCommonPropertyInfo(cpInfo, bamlRecord.AttributeId);
cpInfo.RecordType = _currentBamlRecord.RecordType;
AddToPropertyInfoCollection(cpInfo);
}
/****************************************************************************\
*
* BamlReader.ReadPropertyStringRecord
*
* Read the property record and store the pertinent contents in the
* _properties array list.
*
\***************************************************************************/
private void ReadPropertyStringRecord()
{
string value = MapTable.GetStringFromStringId(((BamlPropertyStringReferenceRecord)_currentBamlRecord).StringId);
AddToPropertyInfoCollection(ReadPropertyRecordCore(value));
}
/****************************************************************************\
*
* BamlReader.ReadPropertyTypeRecord
*
* Read the property record and store the pertinent contents in the
* _properties array list. Convert the TypeId into a fully qualified type
* name.
*
\***************************************************************************/
private void ReadPropertyTypeRecord()
{
BamlPropertyInfo info = new BamlPropertyInfo();
SetCommonPropertyInfo(info,
((BamlPropertyTypeReferenceRecord)_currentBamlRecord).AttributeId);
info.RecordType = _currentBamlRecord.RecordType;
info.Value = GetTypeValueString(((BamlPropertyTypeReferenceRecord)_currentBamlRecord).TypeId);
info.AttributeUsage = BamlAttributeUsage.Default;
AddToPropertyInfoCollection(info);
}
private void ReadPropertyWithExtensionRecord()
{
BamlPropertyInfo info = new BamlPropertyInfo();
SetCommonPropertyInfo(info, ((BamlPropertyWithExtensionRecord)_currentBamlRecord).AttributeId);
info.RecordType = _currentBamlRecord.RecordType;
info.Value = GetExtensionValueString((IOptimizedMarkupExtension)_currentBamlRecord);
info.AttributeUsage = BamlAttributeUsage.Default;
AddToPropertyInfoCollection(info);
}
private void ReadPropertyWithStaticResourceIdRecord()
{
BamlPropertyWithStaticResourceIdRecord bamlPropertyWithStaticResourceIdRecord =
(BamlPropertyWithStaticResourceIdRecord)_currentBamlRecord;
BamlPropertyInfo info = new BamlPropertyInfo();
SetCommonPropertyInfo(info, bamlPropertyWithStaticResourceIdRecord.AttributeId);
info.RecordType = _currentBamlRecord.RecordType;
BamlOptimizedStaticResourceRecord optimizedStaticResourceRecord =
(BamlOptimizedStaticResourceRecord)_currentKeyInfo.StaticResources[bamlPropertyWithStaticResourceIdRecord.StaticResourceId][0];
info.Value = GetExtensionValueString((IOptimizedMarkupExtension)optimizedStaticResourceRecord);
info.AttributeUsage = BamlAttributeUsage.Default;
AddToPropertyInfoCollection(info);
}
/***************************************************************************\
*
* BamlReader.ReadPropertyRecordCore
*
* Read the property record and return the pertinent contents in a
* BamlPropertyInfo record.
*
\***************************************************************************/
private BamlPropertyInfo ReadPropertyRecordCore(string value)
{
BamlPropertyInfo info = new BamlPropertyInfo();
SetCommonPropertyInfo(info,
((BamlPropertyRecord)_currentBamlRecord).AttributeId);
info.RecordType = _currentBamlRecord.RecordType;
info.Value = value;
return info;
}
/****************************************************************************\
*
* BamlReader.ReadPropertyCustomRecord
*
* Read the custom property record and store the pertinent contents in the
* _properties array list. This involves reversing the binary representation
* of the data back into a string using the TypeConverter for the
* property type.
*
\***************************************************************************/
private void ReadPropertyCustomRecord()
{
BamlPropertyInfo info = GetPropertyCustomRecordInfo();
AddToPropertyInfoCollection(info);
}
private BamlPropertyInfo GetPropertyCustomRecordInfo()
{
BamlPropertyInfo info = new BamlPropertyInfo();
BamlAttributeInfoRecord attrInfo = SetCommonPropertyInfo(info,
((BamlPropertyCustomRecord)_currentBamlRecord).AttributeId);
info.RecordType = _currentBamlRecord.RecordType;
info.AttributeUsage = BamlAttributeUsage.Default;
BamlPropertyCustomRecord bamlRecord = (BamlPropertyCustomRecord)_currentBamlRecord;
// Reverse the binary data stored in the record into a string by first getting the
// property. If it has not already been cached in the attribute info record, then
// attempt to resolve it as a DependencyProperty or a PropertyInfo.
if (attrInfo.DP == null && attrInfo.PropInfo == null)
{
attrInfo.DP = MapTable.GetDependencyProperty(attrInfo);
if (attrInfo.OwnerType == null)
{
throw new InvalidOperationException(SR.Get(SRID.BamlReaderNoOwnerType, attrInfo.Name, AssemblyName));
}
if (attrInfo.DP == null)
{
attrInfo.PropInfo = attrInfo.OwnerType.GetProperty(attrInfo.Name,
BindingFlags.Instance | BindingFlags.Public);
if (attrInfo.PropInfo == null)
{
throw new InvalidOperationException(SR.Get(SRID.ParserCantGetDPOrPi, info.Name));
}
}
}
// If we have a property, then get its type and call GetCustomValue,
// which uses the XamlSerializer to turn the binary data into a
// real object
Type propertyType = attrInfo.GetPropertyType();
string propertyName = attrInfo.Name;
short sid = bamlRecord.SerializerTypeId;
// if a Setter of Trigger's Property property is being set, then its value is always
// a DP. Get the attribInfo of this DP property from the ValueId read into the custom
// property record and resolve it into an actual DP instance.
if (sid == (short)KnownElements.DependencyPropertyConverter)
{
Type declaringType = null;
_propertyDP = _bamlRecordReader.GetCustomDependencyPropertyValue(bamlRecord, out declaringType);
declaringType = declaringType == null ? _propertyDP.OwnerType : declaringType;
info.Value = declaringType.Name + "." + _propertyDP.Name;
string xmlns = _parserContext.XamlTypeMapper.GetXmlNamespace(declaringType.Namespace,
declaringType.Assembly.FullName);
string prefix = GetXmlnsPrefix(xmlns);
if (prefix != string.Empty)
{
info.Value = prefix + ":" + info.Value;
}
if (!_propertyDP.PropertyType.IsEnum)
{
_propertyDP = null;
}
}
else
{
if (_propertyDP != null)
{
propertyType = _propertyDP.PropertyType;
propertyName = _propertyDP.Name;
_propertyDP = null;
}
object value = _bamlRecordReader.GetCustomValue(bamlRecord, propertyType, propertyName);
// Once we have a real object, turn that back into a string, and store this
// as the value for this property
TypeConverter converter = TypeDescriptor.GetConverter(value.GetType());
info.Value = converter.ConvertToString(null,
TypeConverterHelper.InvariantEnglishUS,
value);
}
return info;
}
/***************************************************************************\
*
* BamlReader.ReadDefAttributeRecord
*
* Read a x: record that contains the object to use as a key when inserting
* the current element into a dictionary.
*
\***************************************************************************/
private void ReadDefAttributeRecord()
{
BamlDefAttributeRecord bamlRecord = (BamlDefAttributeRecord)_currentBamlRecord;
bamlRecord.Name = MapTable.GetStringFromStringId(bamlRecord.NameId);
BamlPropertyInfo info = new BamlPropertyInfo();
info.Value = bamlRecord.Value;
info.AssemblyName = string.Empty;
info.Prefix = (string)_prefixDictionary[XamlReaderHelper.DefinitionNamespaceURI];
info.XmlNamespace = XamlReaderHelper.DefinitionNamespaceURI;
info.ClrNamespace = string.Empty;
info.Name = bamlRecord.Name;
info.LocalName = info.Name;
info.RecordType = BamlRecordType.DefAttribute;
AddToPropertyInfoCollection(info);
}
/***************************************************************************\
*
* BamlReader.ReadPresentationOptionsAttributeRecord
*
* Read a PresentationsOptions: record used for WPF-specific
* parsing options (e.g., PresentationOptions:Freeze).
*
\***************************************************************************/
private void ReadPresentationOptionsAttributeRecord()
{
BamlPresentationOptionsAttributeRecord bamlRecord = (BamlPresentationOptionsAttributeRecord)_currentBamlRecord;
bamlRecord.Name = MapTable.GetStringFromStringId(bamlRecord.NameId);
BamlPropertyInfo info = new BamlPropertyInfo();
info.Value = bamlRecord.Value;
info.AssemblyName = string.Empty;
info.Prefix = (string)_prefixDictionary[XamlReaderHelper.PresentationOptionsNamespaceURI];
info.XmlNamespace = XamlReaderHelper.PresentationOptionsNamespaceURI;
info.ClrNamespace = string.Empty;
info.Name = bamlRecord.Name;
info.LocalName = info.Name;
info.RecordType = BamlRecordType.PresentationOptionsAttribute;
AddToPropertyInfoCollection(info);
}
/***************************************************************************\
*
* BamlReader.ReadDefAttributeKeyTypeRecord
*
* Read a x: record that contains the object to use as a key when inserting
* the current element into a dictionary.
*
\***************************************************************************/
private void ReadDefAttributeKeyTypeRecord()
{
BamlDefAttributeKeyTypeRecord bamlRecord = (BamlDefAttributeKeyTypeRecord)_currentBamlRecord;
BamlPropertyInfo info = new BamlPropertyInfo();
info.Value = GetTypeValueString(bamlRecord.TypeId);
info.AssemblyName = string.Empty;
info.Prefix = (string)_prefixDictionary[XamlReaderHelper.DefinitionNamespaceURI];
info.XmlNamespace = XamlReaderHelper.DefinitionNamespaceURI;
info.ClrNamespace = string.Empty;
info.Name = XamlReaderHelper.DefinitionName;
info.LocalName = info.Name;
info.RecordType = BamlRecordType.DefAttribute;
AddToPropertyInfoCollection(info);
}
/****************************************************************************\
*
* BamlReader.ReadDeferableContentRecord
*
* Read defered content section of a baml file. Note that this is written
* to baml with the following format:
* BamlDeferableContentStartRecord
* BamlDefAttributeKeyString/Type records, one for each value
* BamlElementStartRecord, one for each value
* BamlRecords within the element
* BamlElementEndRecord
*
* This is presented to the user like a 'normal' dictionary, so here is
* what the user should see:
* ElementStart for the dictionary
* ElementStart, one for each value
* DictionaryKey record, one for each value
* Records within the element
* ElementEnd
* ElementEnd for the dictionary
*
* To do this, queue up the entire contents of the Deferable block and
* re-arrange the records.
*
\***************************************************************************/
private void ReadDeferableContentRecord()
{
_deferableContentBlockDepth = _nodeStack.Count;
// The start of a block of deferable content has been reached. Build
// a key table that will be inserted into the Values as they are loaded.
_deferableContentPosition = ReadDeferKeys();
}
/***************************************************************************\
*
* BamlReader.ReadDeferKeys
*
* Read the keys in a defered content section, and build a table that holds
* these records. These keys are automagically inserted into the outer level
* value start element records to make it look like a x:Key attribute.
* Return the baml stream position for the end of the key section to which
* all key offsets are relative
*
\***************************************************************************/
private Int64 ReadDeferKeys()
{
// Keep reading records until we get one that is not processed
Int64 endOfDefKeys = -1;
_deferKeys = new List();
while (!_haveUnprocessedRecord)
{
GetNextRecord();
ProcessDeferKey();
if (!_haveUnprocessedRecord)
{
endOfDefKeys = _bamlRecordReader.StreamPosition;
}
}
return endOfDefKeys;
}
/****************************************************************************\
*
* BamlReader.ProcessDeferKey
*
* Read a single baml record. If it is a defer key, add it to the table of
* keys. If we encounter something that is not a 'key', then set the
*_haveUnprocessedRecord flag.
*
\***************************************************************************/
private void ProcessDeferKey()
{
switch (_currentBamlRecord.RecordType)
{
// The following three records are internal to the BAMLReader and
// are not exposed publicly. They are used to update the map table
// that maps ids to assemblies, types and attributes.
case BamlRecordType.DefAttributeKeyString:
BamlDefAttributeKeyStringRecord stringKeyRecord = _currentBamlRecord as BamlDefAttributeKeyStringRecord;
if (stringKeyRecord != null)
{
BamlKeyInfo info;
// The "Shared"ness is stored in the BAML with the Key
// But at the XAML level it is a sibling attribute of the key.
info = CheckForSharedness();
if (null != info)
_deferKeys.Add(info);
// Get the value string from the string table, and cache it in the
// record.
stringKeyRecord.Value = MapTable.GetStringFromStringId(
stringKeyRecord.ValueId);
// Add information to the key list to indicate we have a x:Key
// attribute
info = new BamlKeyInfo();
info.Value = stringKeyRecord.Value;
info.AssemblyName = string.Empty;
info.Prefix = (string)_prefixDictionary[XamlReaderHelper.DefinitionNamespaceURI];
info.XmlNamespace = XamlReaderHelper.DefinitionNamespaceURI;
info.ClrNamespace = string.Empty;
info.Name = XamlReaderHelper.DefinitionName;
info.LocalName = info.Name;
info.RecordType = BamlRecordType.DefAttribute;
info.Offset = ((IBamlDictionaryKey)stringKeyRecord).ValuePosition;
_deferKeys.Add(info);
}
break;
case BamlRecordType.DefAttributeKeyType:
BamlDefAttributeKeyTypeRecord typeKeyRecord = _currentBamlRecord as BamlDefAttributeKeyTypeRecord;
if (typeKeyRecord != null)
{
// Translate the type information held in the baml record into
// the {x:Type prefix:Classname} format that would be used on
// a x:Key attribute.
string typeExtensionPrefix = (string)_prefixDictionary[XamlReaderHelper.DefinitionNamespaceURI];
string typeExtensionName;
if (typeExtensionPrefix != string.Empty)
{
typeExtensionName = "{" + typeExtensionPrefix + ":Type ";
}
else
{
typeExtensionName = "{Type ";
}
BamlTypeInfoRecord typeInfo = MapTable.GetTypeInfoFromId(typeKeyRecord.TypeId);
string typeName = typeInfo.TypeFullName;
typeName = typeName.Substring(typeName.LastIndexOf(".", StringComparison.Ordinal) + 1);
string assemblyName;
string prefix;
string xmlNamespace;
GetAssemblyAndPrefixAndXmlns(typeInfo, out assemblyName, out prefix, out xmlNamespace);
if (prefix != string.Empty)
{
typeName = typeExtensionName + prefix + ":" + typeName + "}";
}
else
{
typeName = typeExtensionName + typeName + "}";
}
// Add information to the key list to indicate we have a x:Key
// attribute
BamlKeyInfo info = new BamlKeyInfo();
info.Value = typeName;
info.AssemblyName = string.Empty;
info.Prefix = typeExtensionPrefix;
info.XmlNamespace = XamlReaderHelper.DefinitionNamespaceURI;
info.ClrNamespace = string.Empty;
info.Name = XamlReaderHelper.DefinitionName;
info.LocalName = info.Name;
info.RecordType = BamlRecordType.DefAttribute;
info.Offset = ((IBamlDictionaryKey)typeKeyRecord).ValuePosition;
_deferKeys.Add(info);
}
break;
case BamlRecordType.KeyElementStart:
{
BamlKeyInfo info;
// The "Shared"ness is stored in the BAML with the Key
// But at the XAML level it is a sibling attribute of the key.
info = CheckForSharedness();
if(null != info)
_deferKeys.Add(info);
// Process the subtree that is stored as part of a key tree and
// translate this back into a compact MarkupExtension string.
// Add information to the key list to indicate we have a x:Key
// with a MarkupExtension
info = ProcessKeyTree();
_deferKeys.Add(info);
}
break;
case BamlRecordType.StaticResourceStart:
case BamlRecordType.OptimizedStaticResource:
{
// Process the subtree stored as part of a StaticResource
List srRecords = new List();
// This is for the start record
_currentBamlRecord.Pin();
srRecords.Add(_currentBamlRecord);
// Note that BamlOptmizedStaticResourceRecord is a singleton record
if (_currentBamlRecord.RecordType == BamlRecordType.StaticResourceStart)
{
// Process the subtree that is stored as part of this static resource
ProcessStaticResourceTree(srRecords);
}
// Add the current StaticResource record to the list of StaticResources held per key
BamlKeyInfo keyInfo = _deferKeys[_deferKeys.Count-1];
keyInfo.StaticResources.Add(srRecords);
}
break;
// Any other record types are not processed here
default:
_haveUnprocessedRecord = true;
break;
}
}
private BamlKeyInfo CheckForSharedness()
{
IBamlDictionaryKey dictKey = (IBamlDictionaryKey)_currentBamlRecord;
Debug.Assert(dictKey != null, "Bad Key record");
if (!dictKey.SharedSet)
return null;
BamlKeyInfo info = new BamlKeyInfo();
info.Value = dictKey.Shared.ToString();
info.AssemblyName = string.Empty;
info.Prefix = (string)_prefixDictionary[XamlReaderHelper.DefinitionNamespaceURI];
info.XmlNamespace = XamlReaderHelper.DefinitionNamespaceURI;
info.ClrNamespace = string.Empty;
info.Name = XamlReaderHelper.DefinitionShared;
info.LocalName = info.Name;
info.RecordType = BamlRecordType.DefAttribute;
info.Offset = dictKey.ValuePosition;
return info;
}
/****************************************************************************\
*
* BamlReader.ProcessKeyTree
*
* Read a tree of baml records that make up a dictionary key and translate them
* back in the compact syntax representation of a MarkupExtension section.
* When we encounter KeyElementEnd record, then stop.
*
\***************************************************************************/
private BamlKeyInfo ProcessKeyTree()
{
BamlKeyElementStartRecord keyStartRecord = _currentBamlRecord as BamlKeyElementStartRecord;
Debug.Assert(keyStartRecord != null, "Bad Key Element Start record");
// Translate the type information held in the baml record into
// the "{prefix:Classname " format that would be used on
// a x:Key attribute.
BamlTypeInfoRecord typeInfo = MapTable.GetTypeInfoFromId(keyStartRecord.TypeId);
string markupString = typeInfo.TypeFullName;
markupString = markupString.Substring(markupString.LastIndexOf(".", StringComparison.Ordinal) + 1);
string assemblyName;
string prefix;
string xmlNamespace;
GetAssemblyAndPrefixAndXmlns(typeInfo, out assemblyName, out prefix, out xmlNamespace);
if (prefix != string.Empty)
{
markupString = "{" + prefix + ":" + markupString + " ";
}
else
{
markupString = "{" + markupString + " ";
}
bool notDone = true;
BamlNodeInfo nodeInfo;
// Keep track of whether we have written a property or not at a given nesting
// level so that we know when to add commas between properties. Also keep
// track of when we have entered a constructor parameter section and when
// we have written out the first parameter to handle adding commas between
// constructor parameters.
Stack readProperty = new Stack();
Stack readConstructor = new Stack();
Stack readFirstConstructor = new Stack();
readProperty.Push(false); // Property has not yet been read
readConstructor.Push(false); // Constructor section has not been read
readFirstConstructor.Push(false); // First constructor parameter has not been read
while (notDone)
{
// Read the next record. Some of the processing below reads ahead one
// record and sets _haveUnprocessedRecord to true, in which case we
// don't want to read another one.
if (!_haveUnprocessedRecord)
{
GetNextRecord();
}
else
{
_haveUnprocessedRecord = false;
}
switch (_currentBamlRecord.RecordType)
{
// The following five records are internal to the BAMLReader and
// are not exposed publicly. They are used to update the map table
// that maps ids to assemblies, types and attributes.
case BamlRecordType.AssemblyInfo:
ReadAssemblyInfoRecord();
break;
case BamlRecordType.TypeInfo:
case BamlRecordType.TypeSerializerInfo:
MapTable.LoadTypeInfoRecord((BamlTypeInfoRecord)_currentBamlRecord);
break;
case BamlRecordType.AttributeInfo:
MapTable.LoadAttributeInfoRecord((BamlAttributeInfoRecord)_currentBamlRecord);
break;
case BamlRecordType.StringInfo:
MapTable.LoadStringInfoRecord((BamlStringInfoRecord)_currentBamlRecord);
break;
case BamlRecordType.PropertyComplexStart:
ReadPropertyComplexStartRecord();
nodeInfo = (BamlNodeInfo)_nodeStack.Pop();
if ((bool)readProperty.Pop())
{
markupString += ", ";
}
markupString += nodeInfo.LocalName + "=";
readProperty.Push(true);
break;
case BamlRecordType.PropertyComplexEnd:
break;
case BamlRecordType.Text:
case BamlRecordType.TextWithId:
BamlTextWithIdRecord textWithIdRecord = _currentBamlRecord as BamlTextWithIdRecord;
if (textWithIdRecord != null)
{
// Get the value string from the string table, and cache it in the
// record.
textWithIdRecord.Value = MapTable.GetStringFromStringId(
textWithIdRecord.ValueId);
}
// If the text contains '{' or '}' then we have to escape these
// so that it won't be interpreted as a MarkupExtension
string escapedString = EscapeString(((BamlTextRecord)_currentBamlRecord).Value);
if ((bool)readFirstConstructor.Peek())
{
markupString += ", ";
}
markupString += escapedString;
if ((bool)readConstructor.Peek())
{
readFirstConstructor.Pop();
readFirstConstructor.Push(true);
}
break;
case BamlRecordType.ElementStart:
// Process commas between constructor parameters
if ((bool)readFirstConstructor.Peek())
{
markupString += ", ";
}
if ((bool)readConstructor.Peek())
{
readFirstConstructor.Pop();
readFirstConstructor.Push(true);
}
// Setup for the next level
readProperty.Push(false);
readConstructor.Push(false);
readFirstConstructor.Push(false);
// Write element type. Translate the type information held in the
// baml record into the "prefix:Classname" format
BamlElementStartRecord elementStartRecord = _currentBamlRecord as BamlElementStartRecord;
BamlTypeInfoRecord elementTypeInfo = MapTable.GetTypeInfoFromId(elementStartRecord.TypeId);
string typename = elementTypeInfo.TypeFullName;
typename = typename.Substring(typename.LastIndexOf(".", StringComparison.Ordinal) + 1);
GetAssemblyAndPrefixAndXmlns(elementTypeInfo, out assemblyName, out prefix, out xmlNamespace);
if (prefix != string.Empty)
{
markupString += "{" + prefix + ":" + typename + " ";
}
else
{
markupString = "{" + typename + " ";
}
break;
case BamlRecordType.ElementEnd:
readProperty.Pop();
readConstructor.Pop();
readFirstConstructor.Pop();
markupString += "}";
break;
case BamlRecordType.ConstructorParametersStart:
readConstructor.Pop();
readConstructor.Push(true);
break;
case BamlRecordType.ConstructorParametersEnd:
readConstructor.Pop();
readConstructor.Push(false);
readFirstConstructor.Pop();
readFirstConstructor.Push(false);
break;
case BamlRecordType.ConstructorParameterType:
// Process commas between constructor parameters
if ((bool)readFirstConstructor.Peek())
{
markupString += ", ";
}
if ((bool)readConstructor.Peek())
{
readFirstConstructor.Pop();
readFirstConstructor.Push(true);
}
BamlConstructorParameterTypeRecord constTypeRecord = _currentBamlRecord as BamlConstructorParameterTypeRecord;
markupString += GetTypeValueString(constTypeRecord.TypeId);
break;
case BamlRecordType.Property:
case BamlRecordType.PropertyWithConverter:
{
string value = ((BamlPropertyRecord)_currentBamlRecord).Value;
BamlPropertyInfo propertyInfo = ReadPropertyRecordCore(value);
if ((bool)readProperty.Pop())
{
markupString += ", ";
}
markupString += propertyInfo.LocalName + "=" + propertyInfo.Value;
readProperty.Push(true);
}
break;
case BamlRecordType.PropertyCustom:
{
BamlPropertyInfo propertyInfo = GetPropertyCustomRecordInfo();
if ((bool)readProperty.Pop())
{
markupString += ", ";
}
markupString += propertyInfo.LocalName + "=" + propertyInfo.Value;
readProperty.Push(true);
}
break;
case BamlRecordType.PropertyStringReference:
{
string value = MapTable.GetStringFromStringId(((BamlPropertyStringReferenceRecord)_currentBamlRecord).StringId);
BamlPropertyInfo propertyInfo = ReadPropertyRecordCore(value);
if ((bool)readProperty.Pop())
{
markupString += ", ";
}
markupString += propertyInfo.LocalName + "=" + propertyInfo.Value;
readProperty.Push(true);
}
break;
case BamlRecordType.PropertyTypeReference:
{
string value = GetTypeValueString(((BamlPropertyTypeReferenceRecord)_currentBamlRecord).TypeId);
string attributeName = MapTable.GetAttributeNameFromId(
((BamlPropertyTypeReferenceRecord)_currentBamlRecord).AttributeId);
if ((bool)readProperty.Pop())
{
markupString += ", ";
}
markupString += attributeName + "=" + value;
readProperty.Push(true);
}
break;
case BamlRecordType.PropertyWithExtension:
{
string value = GetExtensionValueString((BamlPropertyWithExtensionRecord)_currentBamlRecord);
string attributeName = MapTable.GetAttributeNameFromId(
((BamlPropertyWithExtensionRecord)_currentBamlRecord).AttributeId);
if ((bool)readProperty.Pop())
{
markupString += ", ";
}
markupString += attributeName + "=" + value;
readProperty.Push(true);
}
break;
case BamlRecordType.KeyElementEnd:
markupString += "}";
notDone = false;
_haveUnprocessedRecord = false;
break;
default:
// Can't have any other type of record at this point.
throw new InvalidOperationException(SR.Get(SRID.ParserUnknownBaml,
((int)_currentBamlRecord.RecordType).ToString(CultureInfo.CurrentCulture)));
}
}
// At this point the markup string representing the MarkupExtension should
// be complete, so set this as the value for this key.
BamlKeyInfo info = new BamlKeyInfo();
info.Value = markupString;
info.AssemblyName = string.Empty;
info.Prefix = (string)_prefixDictionary[XamlReaderHelper.DefinitionNamespaceURI];
info.XmlNamespace = XamlReaderHelper.DefinitionNamespaceURI;
info.ClrNamespace = string.Empty;
info.Name = XamlReaderHelper.DefinitionName;
info.LocalName = info.Name;
info.RecordType = BamlRecordType.DefAttribute;
info.Offset = ((IBamlDictionaryKey)keyStartRecord).ValuePosition;
return info;
}
///
/// Picks up all the BamlRecords for a front loaded static resource into a
/// list of BamlRecords.
///
private void ProcessStaticResourceTree(List srRecords)
{
bool notDone = true;
while (notDone)
{
// We may already have a record that was previously read in but not
// processed. This occurs when we've looped through all the properties
// on an element and have encountered a non-property record to stop
// the loop. In that case don't read another record and just process
// the one we have.
if (_haveUnprocessedRecord)
{
_haveUnprocessedRecord = false;
}
else
{
GetNextRecord();
}
// Remember the BamlRecords beloning to this StaticResource
_currentBamlRecord.Pin();
srRecords.Add(_currentBamlRecord);
if (_currentBamlRecord.RecordType == BamlRecordType.StaticResourceEnd)
{
notDone = false;
}
}
}
///
/// Picks up the list of BamlRecords in the deferred
/// section corresponding to this StaticResourceId
///
private void ReadStaticResourceId()
{
BamlStaticResourceIdRecord bamlRecord = (BamlStaticResourceIdRecord)_currentBamlRecord;
_currentStaticResourceRecords = _currentKeyInfo.StaticResources[bamlRecord.StaticResourceId];
_currentStaticResourceRecordIndex = 0;
}
/***************************************************************************\
*
* BamlReader.EscapeString
*
* Check for '{' and '}' and escape any that are found in the passed value.
* Don't create a new string unless you have to.
*
\***************************************************************************/
private string EscapeString(string value)
{
StringBuilder builder = null;
for (int i=0; i 0)
{
_ownerTypeName = nodeInfo.Name.Substring(0, index);
}
else
{
// Eg. xmlns property
_ownerTypeName = string.Empty;
}
_name = nodeInfo.Name;
_clrNamespace = nodeInfo.ClrNamespace;
_assemblyName = nodeInfo.AssemblyName;
_prefix = nodeInfo.Prefix;
_xmlNamespace = nodeInfo.XmlNamespace;
nodeInfo.RecordType = _currentBamlRecord.RecordType;
_nodeStack.Push(nodeInfo);
// Read the properties that may be part of the start tag
ReadProperties();
}
/****************************************************************************\
*
* BamlReader.ReadPropertyComplexEndRecord
*
* Read the end of a complex property. This can be any type of complex
* property, including arrays, ILists, IDictionaries, Clr properties or
* dependency properties.
*
\***************************************************************************/
private void ReadPropertyComplexEndRecord()
{
// Pop information off the node info stack that tells us what the starting
// record was for this ending record. Check to make sure it is the
// correct type. If not, throw an exception.
BamlNodeInfo nodeInfo = (BamlNodeInfo)_nodeStack.Pop();
BamlRecordType expectedType;
switch (nodeInfo.RecordType)
{
case BamlRecordType.PropertyComplexStart:
expectedType = BamlRecordType.PropertyComplexEnd;
break;
case BamlRecordType.PropertyArrayStart:
expectedType = BamlRecordType.PropertyArrayEnd;
break;
case BamlRecordType.PropertyIListStart:
expectedType = BamlRecordType.PropertyIListEnd;
break;
case BamlRecordType.PropertyIDictionaryStart:
expectedType = BamlRecordType.PropertyIDictionaryEnd;
break;
default:
expectedType = BamlRecordType.Unknown;
break;
}
if (_currentBamlRecord.RecordType != expectedType)
{
throw new InvalidOperationException(SR.Get(SRID.BamlScopeError,
_currentBamlRecord.RecordType.ToString(),
expectedType.ToString()));
}
ClearProperties();
NodeTypeInternal = BamlNodeType.EndComplexProperty;
_name = nodeInfo.Name;
_localName = nodeInfo.LocalName;
int index = nodeInfo.Name.LastIndexOf(".", StringComparison.Ordinal);
if (index > 0)
{
_ownerTypeName = nodeInfo.Name.Substring(0, index);
}
else
{
// Eg. xmlns property
_ownerTypeName = string.Empty;
}
_assemblyName = nodeInfo.AssemblyName;
_prefix = nodeInfo.Prefix;
_xmlNamespace = nodeInfo.XmlNamespace;
_clrNamespace = nodeInfo.ClrNamespace;
_parserContext.PopScope();
_prefixDictionary.PopScope();
ReadProperties();
}
/***************************************************************************\
*
* BamlReader.ReadTextRecord
*
* Read record containing text content that goes between the start and end
* tags of an object.
*
\***************************************************************************/
private void ReadTextRecord()
{
ClearProperties();
BamlTextWithIdRecord textWithIdRecord = _currentBamlRecord as BamlTextWithIdRecord;
if (textWithIdRecord != null)
{
// Get the value string from the string table, and cache it in the
// record.
textWithIdRecord.Value = MapTable.GetStringFromStringId(
textWithIdRecord.ValueId);
}
BamlTextWithConverterRecord textWithConverter = _currentBamlRecord as BamlTextWithConverterRecord;
if (textWithConverter != null)
{
short converterTypeId = textWithConverter.ConverterTypeId;
Type converter = MapTable.GetTypeFromId(converterTypeId);
_typeConverterAssemblyName = converter.Assembly.FullName;
_typeConverterName = converter.FullName;
}
NodeTypeInternal = BamlNodeType.Text;
_prefix = string.Empty;
_value = ((BamlTextRecord)_currentBamlRecord).Value;
}
/***************************************************************************\
*
* BamlReader.ReadConstructorStart
*
* Read a start tag, which indicates that
* the following objects are to be used as constructor parameters.
*
\***************************************************************************/
private void ReadConstructorStart()
{
ClearProperties();
NodeTypeInternal = BamlNodeType.StartConstructor;
// Push information on the node stack to indicate we have a start array
BamlNodeInfo nodeInfo = new BamlNodeInfo();
nodeInfo.RecordType = BamlRecordType.ConstructorParametersStart;
_nodeStack.Push(nodeInfo);
}
/***************************************************************************\
*
* BamlReader.ReadConstructorEnd
*
* Read a <\x:ConstructorParameters ... > end tag, which indicates that
* the previous objects are to be used as constructor parameters.
*
\***************************************************************************/
private void ReadConstructorEnd()
{
ClearProperties();
NodeTypeInternal = BamlNodeType.EndConstructor;
// Pop information off the node stack that tells us what element this
// is the end of. Check to make sure the record on the stack is for a
// start element.
BamlNodeInfo nodeInfo = (BamlNodeInfo)_nodeStack.Pop();
if (nodeInfo.RecordType != BamlRecordType.ConstructorParametersStart)
{
throw new InvalidOperationException(SR.Get(SRID.BamlScopeError,
_currentBamlRecord.RecordType.ToString(),
BamlRecordType.ConstructorParametersEnd.ToString()));
}
// read properties, if any, after this end tag.
ReadProperties();
}
/****************************************************************************\
*
* BamlReader.InsertDeferedKey
*
* Search the _deferedKeys list for a dictionary key that has the same offset
* as the current baml stream position. If one is found, generate a
* def attribute record to simulate a dictionary key.
*
\***************************************************************************/
private void InsertDeferedKey(Int32 valueOffset)
{
if (_deferKeys == null)
{
return;
}
BamlKeyInfo keyInfo = _deferKeys[0];
while (keyInfo.Offset == valueOffset)
{
// Remember the _currentKeyInfo so that we can use it to resolve StaticResourceId
// records that may occur within the corresponding value.
_currentKeyInfo = keyInfo;
BamlPropertyInfo info = new BamlPropertyInfo();
info.Value = keyInfo.Value;
info.AssemblyName = string.Empty;
info.Prefix = (string)_prefixDictionary[XamlReaderHelper.DefinitionNamespaceURI];
info.XmlNamespace = XamlReaderHelper.DefinitionNamespaceURI;
info.ClrNamespace = string.Empty;
info.Name = keyInfo.Name;
info.LocalName = info.Name;
info.RecordType = BamlRecordType.DefAttribute;
AddToPropertyInfoCollection(info);
// We no longer need this key record, so remove it to make subsequent
// searches faster.
_deferKeys.RemoveAt(0);
if (_deferKeys.Count > 0)
{
keyInfo = _deferKeys[0];
}
else
{
return;
}
}
}
/***************************************************************************\
*
* BamlReader.ClearProperties
*
* Clear properties that are likely to change as different baml records
* are read in.
*
\***************************************************************************/
private void ClearProperties()
{
_value = string.Empty;
_prefix = string.Empty;
_name = string.Empty;
_localName = string.Empty;
_ownerTypeName = string.Empty;
_assemblyName = string.Empty;
_xmlNamespace = string.Empty;
_clrNamespace = string.Empty;
_connectionId = 0;
_contentPropertyName = string.Empty;
_attributeUsage = BamlAttributeUsage.Default;
_typeConverterAssemblyName = string.Empty;
_typeConverterName = string.Empty;
_properties.Clear();
}
/****************************************************************************\
*
* BamlReader.SetCommonPropertyInfo
*
* Get information that is common to all types of property records and
* fill in the passed node info record with this information.
* Return the attribute info found.
*
\***************************************************************************/
private BamlAttributeInfoRecord SetCommonPropertyInfo(
BamlNodeInfo nodeInfo,
short attrId)
{
BamlAttributeInfoRecord attrInfo = MapTable.GetAttributeInfoFromId(attrId);
BamlTypeInfoRecord typeInfo = MapTable.GetTypeInfoFromId(attrInfo.OwnerTypeId);
// Fill node info record with this data.
nodeInfo.LocalName = attrInfo.Name;
nodeInfo.Name = typeInfo.TypeFullName + "." + nodeInfo.LocalName;
string assembly, prefix, namespaceUri;
GetAssemblyAndPrefixAndXmlns(typeInfo, out assembly, out prefix, out namespaceUri);
nodeInfo.AssemblyName = assembly;
nodeInfo.Prefix = prefix;
nodeInfo.XmlNamespace = namespaceUri;
nodeInfo.ClrNamespace = typeInfo.ClrNamespace;
nodeInfo.AttributeUsage = attrInfo.AttributeUsage;
return attrInfo;
}
private string GetTemplateBindingExtensionValueString(short memberId)
{
string valueString = string.Empty;
string valuePrefix = null;
string typeName = null;
string propName = null;
if (memberId < 0)
{
memberId = (short)-memberId;
DependencyProperty dp = null;
if (memberId < (short)KnownProperties.MaxDependencyProperty)
{
KnownProperties knownId = (KnownProperties)(memberId);
{
dp = KnownTypes.GetKnownDependencyPropertyFromId(knownId);
}
}
if (dp == null)
{
throw new InvalidOperationException(SR.Get(SRID.BamlBadExtensionValue));
}
else
{
typeName = dp.OwnerType.Name;
propName = dp.Name;
}
object prefixObject = _prefixDictionary[XamlReaderHelper.DefaultNamespaceURI];
valuePrefix = (prefixObject == null) ? string.Empty : (string)prefixObject;
}
else
{
BamlAttributeInfoRecord attrInfo = MapTable.GetAttributeInfoFromId(memberId);
BamlTypeInfoRecord valueTypeInfo = MapTable.GetTypeInfoFromId(attrInfo.OwnerTypeId);
string valueXmlNamespace;
string valueAssemblyName;
GetAssemblyAndPrefixAndXmlns(valueTypeInfo, out valueAssemblyName, out valuePrefix, out valueXmlNamespace);
typeName = valueTypeInfo.TypeFullName;
typeName = typeName.Substring(typeName.LastIndexOf(".", StringComparison.Ordinal) + 1);
propName = attrInfo.Name;
}
if (valuePrefix == string.Empty)
{
valueString += typeName;
}
else
{
valueString += valuePrefix + ":" + typeName;
}
valueString += "." + propName + "}";
return valueString;
}
private string GetStaticExtensionValueString(short memberId)
{
string valueString = string.Empty;
string valuePrefix = null;
string typeName = null;
string propName = null;
string extensionPrefix = (string)_prefixDictionary[XamlReaderHelper.DefinitionNamespaceURI];
if (extensionPrefix != string.Empty)
{
valueString = "{" + extensionPrefix + ":Static ";
}
else
{
valueString = "{Static ";
}
if (memberId < 0)
{
memberId = (short)-memberId;
bool isKey = true;
// this is a known StaticExtension param.
// if keyId is more than the range it is the actual resource,
// else it is the key.
if (memberId > (short)SystemResourceKeyID.InternalSystemThemeStylesEnd)
{
memberId -= (short)SystemResourceKeyID.InternalSystemThemeStylesEnd;
isKey = false;
}
if (Enum.IsDefined(typeof(SystemResourceKeyID), (int)memberId))
{
SystemResourceKeyID keyId = (SystemResourceKeyID)memberId;
typeName = SystemKeyConverter.GetSystemClassName(keyId);
if (isKey)
{
propName = SystemKeyConverter.GetSystemKeyName(keyId);
}
else
{
propName = SystemKeyConverter.GetSystemPropertyName(keyId);
}
}
else
{
throw new InvalidOperationException(SR.Get(SRID.BamlBadExtensionValue));
}
object prefixObject = _prefixDictionary[XamlReaderHelper.DefaultNamespaceURI];
valuePrefix = (prefixObject == null) ? string.Empty : (string)prefixObject;
}
else
{
BamlAttributeInfoRecord attrInfo = MapTable.GetAttributeInfoFromId(memberId);
BamlTypeInfoRecord valueTypeInfo = MapTable.GetTypeInfoFromId(attrInfo.OwnerTypeId);
string valueXmlNamespace;
string valueAssemblyName;
GetAssemblyAndPrefixAndXmlns(valueTypeInfo, out valueAssemblyName, out valuePrefix, out valueXmlNamespace);
typeName = valueTypeInfo.TypeFullName;
typeName = typeName.Substring(typeName.LastIndexOf(".", StringComparison.Ordinal) + 1);
propName = attrInfo.Name;
}
if (valuePrefix == string.Empty)
{
valueString += typeName;
}
else
{
valueString += valuePrefix + ":" + typeName;
}
valueString += "." + propName + "}";
return valueString;
}
private string GetExtensionPrefixString(string extensionName)
{
string valueString = string.Empty;
string extensionPrefix = (string)_prefixDictionary[XamlReaderHelper.DefaultNamespaceURI];
if (!string.IsNullOrEmpty(extensionPrefix))
{
valueString = "{" + extensionPrefix + ":" + extensionName + " ";
}
else
{
valueString = "{" + extensionName + " ";
}
return valueString;
}
private string GetInnerExtensionValueString(IOptimizedMarkupExtension optimizedMarkupExtensionRecord)
{
string valueString = string.Empty;
short memberId = optimizedMarkupExtensionRecord.ValueId;
if (optimizedMarkupExtensionRecord.IsValueTypeExtension)
{
valueString = GetTypeValueString(memberId);
}
else if (optimizedMarkupExtensionRecord.IsValueStaticExtension)
{
valueString = GetStaticExtensionValueString(memberId);
}
else
{
valueString = MapTable.GetStringFromStringId(memberId);
}
return valueString + "}";
}
private string GetExtensionValueString(IOptimizedMarkupExtension optimizedMarkupExtensionRecord)
{
string valueString = string.Empty;
short memberId = optimizedMarkupExtensionRecord.ValueId;
short extensionId = optimizedMarkupExtensionRecord.ExtensionTypeId;
switch (extensionId)
{
case (short)KnownElements.StaticExtension:
valueString = GetStaticExtensionValueString(memberId);
break;
case (short)KnownElements.TemplateBindingExtension:
valueString = GetExtensionPrefixString("TemplateBinding");
valueString += GetTemplateBindingExtensionValueString(memberId);
break;
case (short)KnownElements.DynamicResourceExtension:
valueString = GetExtensionPrefixString("DynamicResource");
valueString += GetInnerExtensionValueString(optimizedMarkupExtensionRecord);
break;
case (short)KnownElements.StaticResourceExtension:
valueString = GetExtensionPrefixString("StaticResource");
valueString += GetInnerExtensionValueString(optimizedMarkupExtensionRecord);
break;
}
return valueString;
}
/****************************************************************************\
*
* BamlReader.GetTypeValueString
*
* Construct a MarkupExtension that represents the type given its ID in the
* BamlMapTable.
*
\***************************************************************************/
private string GetTypeValueString(short typeId)
{
string typeExtensionPrefix = (string)_prefixDictionary[XamlReaderHelper.DefinitionNamespaceURI];
string valueString;
if (typeExtensionPrefix != string.Empty)
{
valueString = "{" + typeExtensionPrefix + ":Type ";
}
else
{
valueString = "{Type ";
}
BamlTypeInfoRecord valueTypeInfo = MapTable.GetTypeInfoFromId(typeId);
string valueXmlNamespace;
string valuePrefix;
string valueAssemblyName;
GetAssemblyAndPrefixAndXmlns(valueTypeInfo, out valueAssemblyName, out valuePrefix, out valueXmlNamespace);
string typeName = valueTypeInfo.TypeFullName;
typeName = typeName.Substring(typeName.LastIndexOf(".", StringComparison.Ordinal) + 1);
if (valuePrefix == string.Empty)
{
valueString += typeName;
}
else
{
valueString += valuePrefix + ":" + typeName;
}
valueString +="}";
return valueString;
}
/***************************************************************************\
*
* BamlReader.GetAssemblyAndPrefixAndXmlns
*
* Get a namespace prefix and the associated Xml namespace for a given type.
* If none, return empty strings.
*
\***************************************************************************/
private void GetAssemblyAndPrefixAndXmlns(
BamlTypeInfoRecord typeInfo,
out string assemblyFullName,
out string prefix,
out string xmlns)
{
// If the typeInfo indicates the type is NOT a core Avalon type, then the
// assembly should be in the Assembly table of the BamlMapTable. Otherwise
// we have to get the Assembly information from the actual type.
if (typeInfo.AssemblyId >= 0 || typeInfo.Type == null)
{
BamlAssemblyInfoRecord assyInfo = MapTable.GetAssemblyInfoFromId(
typeInfo.AssemblyId);
assemblyFullName = assyInfo.AssemblyFullName;
}
else
{
Assembly typeAssembly = typeInfo.Type.Assembly;
assemblyFullName = typeAssembly.FullName;
}
// Look through the mapping table for an xml namespace that matches
// the assembly and type namespace.
// Note that it may be one of the known namespaces, such as the definition
// namespace so check for that first.
if (typeInfo.ClrNamespace == "System.Windows.Markup" &&
(assemblyFullName.StartsWith("PresentationFramework", StringComparison.Ordinal)
|| assemblyFullName.StartsWith("System.Xaml", StringComparison.Ordinal)))
{
xmlns = XamlReaderHelper.DefinitionNamespaceURI;
}
else
{
// XamlTypeMapper only stored MappingPI Xml Namesaces
xmlns = _parserContext.XamlTypeMapper.GetXmlNamespace(
typeInfo.ClrNamespace, assemblyFullName);
// Now check our own private list for URI based Xml Namespaces
if(String.IsNullOrEmpty(xmlns))
{
List xmlnsList = GetXmlNamespaceList(typeInfo.ClrNamespace, assemblyFullName);
prefix = GetXmlnsPrefix(xmlnsList);
return;
}
}
prefix = GetXmlnsPrefix(xmlns);
}
// store the all XmlNs UIRs that map to each CLRNamespace + AssemblyName
private void SetXmlNamespace(string clrNamespace, string assemblyFullName, string xmlNs)
{
String fullName = clrNamespace + "#" + assemblyFullName;
List list;
if(_reverseXmlnsTable.ContainsKey(fullName))
{
list = _reverseXmlnsTable[fullName];
}
else
{
list = new List();
_reverseXmlnsTable[fullName] = list;
}
list.Add(xmlNs);
}
// Retrieve the XmlNs UIRs that map to a CLRNamespace + AssemblyName
private List GetXmlNamespaceList(string clrNamespace, string assemblyFullName)
{
String fullName = clrNamespace + "#" + assemblyFullName;
List xmlnsList=null;
if (_reverseXmlnsTable.ContainsKey(fullName))
{
xmlnsList = _reverseXmlnsTable[fullName];
}
return xmlnsList;
}
internal string GetXmlnsPrefix(string xmlns)
{
string prefix = string.Empty;
// If we don't find an xmlns, then the clr namespace must be in the
// default definition file group for this file. Otherwise, lookup the
// prefix in the xmlns-to-prefix dictionary built up in ReadXmlnsProperty
if (xmlns == string.Empty)
{
xmlns = _parserContext.XmlnsDictionary[string.Empty];
}
else
{
object prefixObject = _prefixDictionary[xmlns];
// If there is nothing in the prefix dictionary for this namespace,
// then assume this is the default namespace and set prefix to
// an empty string.
if (prefixObject != null)
{
prefix = (string)prefixObject;
}
}
return prefix;
}
private string GetXmlnsPrefix(List xmlnsList)
{
string prefix;
string xmlns;
if (xmlnsList != null)
{
// return the first non-null prefix defined.
// the default prefix is "" and is non-null.
for (int i=0; i _deferKeys;
// Info for the key being currently read.
private BamlKeyInfo _currentKeyInfo;
// The currently active StaticResourceInfo
private List _currentStaticResourceRecords;
private int _currentStaticResourceRecordIndex;
// The type of current BAML node (or a condensed version of the real baml record type)
private BamlNodeType _bamlNodeType;
// The current read state of this BamlReader.
private ReadState _readState;
// The value of the assembly name for the current node
private string _assemblyName;
// The value of the namespace prefix for the current node
private string _prefix;
// Xml namespace for the current node;
private string _xmlNamespace;
// Clr namespace for the current node;
private string _clrNamespace;
// The attribute value for the current node, if a property or namespace
private string _value;
// The fully qualified name of the current node
private string _name;
// The local part of the name of the current node, without class or prefix
private string _localName;
// The fully qualified class name of the current node's owner type, without prefix
// Applies only to properties and events
private string _ownerTypeName;
// Arraylist of various PropertyInfo objects in the order retrieved from the baml stream
private ArrayList _properties;
// DP value of a property. If this is set the type of this property is used to resolve the
// value of any subsequent property. Setter.Property & Setter.Value is an example of this sceanrio.
private DependencyProperty _propertyDP;
// Index of current property in _properties collection that is being viewed.
private int _propertiesIndex;
// connection Id of current element for hooking up IDs and events.
private Int32 _connectionId;
// contentProperty Name of current element.
private string _contentPropertyName;
// Defines what this property is used for such as being an alias for
// xml:lang, xml:space or x:ID
private BamlAttributeUsage _attributeUsage;
// Stack of node information about the element tree being built.
private Stack _nodeStack;
// Context information used when reading baml file. This contains the XamlTypeMapper used
// for resolving binary property information into strings.
private ParserContext _parserContext;
private bool _isInjected;
private bool _useTypeConverter;
private string _typeConverterAssemblyName;
private string _typeConverterName;
// Maps CLRNameSpace#AssemblyFullName <--> List of XmlNamespacesURIs.
private Dictionary> _reverseXmlnsTable;
#endregion Data
/***************************************************************************\
*
* BamlNodeInfo
*
* This class holds information about a single element or other node record
* that is encountered when reading the baml file.
*
\***************************************************************************/
//
// This code should always be transparent. Meaning you should never add
// SecurityCritical to this section of the code.
//
internal class BamlNodeInfo
{
// Create an empty property info record
internal BamlNodeInfo()
{
}
// The type of record, be it element, complex property, array, etc.
internal BamlRecordType RecordType
{
get { return _recordType; }
set { _recordType = value; }
}
// The value of the assembly name for the declaring type of the current node or property
internal string AssemblyName
{
get { return _assemblyName; }
set { _assemblyName = value; }
}
// The value of the namespace prefix for the current node or property
internal string Prefix
{
get { return _prefix; }
set { _prefix = value; }
}
// Xml namespace for the current node or property
internal string XmlNamespace
{
get { return _xmlNamespace; }
set { _xmlNamespace = value; }
}
// Clr namespace for the current node or property
internal string ClrNamespace
{
get { return _clrNamespace; }
set { _clrNamespace = value; }
}
// The fully qualified name of the current node or property
internal string Name
{
get { return _name; }
set { _name = value; }
}
// The local part of the name of the current node or property
internal string LocalName
{
get { return _localName; }
set { _localName = value; }
}
// Defines what this property is used for such as being an alias for
// xml:lang, xml:space or x:ID
internal BamlAttributeUsage AttributeUsage
{
get { return _attributeUsage; }
set { _attributeUsage = value; }
}
// The type of record, be it element, complex property, array, etc.
private BamlRecordType _recordType;
// The value of the assembly name for the declaring type of the current node or property
private string _assemblyName;
// The value of the namespace prefix for the current node or property
private string _prefix;
// Xml namespace for the current node or property
private string _xmlNamespace;
// Clr namespace for the current node or property
private string _clrNamespace;
// The fully qualified name of the current node or property
private string _name;
// The local part of the name of the current node or property
private string _localName;
// Defines what this property is used for such as being an alias for
// xml:lang, xml:space or x:ID
private BamlAttributeUsage _attributeUsage;
}
/***************************************************************************\
*
* BamlPropertyInfo
*
* This class holds information about a single Baml property record that is
* encountered when reading all the property-like records on an element.
*
\***************************************************************************/
//
// This code should always be transparent. Meaning you should never add
// SecurityCritical to this section of the code.
//
internal class BamlPropertyInfo : BamlNodeInfo
{
// Create an empty property info record
internal BamlPropertyInfo()
{
}
// The string value for the current property
internal string Value
{
get { return _value; }
set { _value = value; }
}
// The string value for the current property
private string _value;
}
/***************************************************************************\
*
* BamlContentPropertyInfo
*
* This class holds information about a single Baml property record that is
* encountered when reading all the property-like records on an element.
*
\***************************************************************************/
//
// This code should always be transparent. Meaning you should never add
// SecurityCritical to this section of the code.
//
internal class BamlContentPropertyInfo : BamlNodeInfo
{
// this doesn't need any different fields it just needs to be
// a different type.
}
/****************************************************************************\
*
* BamlKeyInfo
*
* This class holds information about a single Baml property record that is
* encountered when reading all the property-like records on an element.
*
\***************************************************************************/
//
// This code should always be transparent. Meaning you should never add
// SecurityCritical to this section of the code.
//
[DebuggerDisplay("{_offset}")]
internal class BamlKeyInfo : BamlPropertyInfo
{
// Create an empty info record
internal BamlKeyInfo()
{
}
// The offset of the value from the start of the values section.
internal Int32 Offset
{
get { return _offset; }
set { _offset = value; }
}
internal List> StaticResources
{
get
{
if (_staticResources == null)
{
_staticResources = new List>();
}
return _staticResources;
}
}
private Int32 _offset;
private List> _staticResources;
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
/****************************************************************************\
*
* File: BamlReader.cs
*
* Purpose: Public interface for reading BamlRecords with an interface
* that is similar to XmlReader
*
* History:
* 10/09/2003 peterost - created
*
* Copyright (C) 2003 by Microsoft Corporation. All rights reserved.
*
\***************************************************************************/
using System;
using System.Xml;
using System.IO;
using System.Windows;
using System.Windows.Navigation;
using System.Text;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;
using System.Windows.Threading;
using System.Globalization;
using MS.Utility;
using MS.Internal;
namespace System.Windows.Markup
{
///
/// Type of BAML node at the current BamlReader location in
/// the BAML stream.
///
internal enum BamlNodeType
{
///
/// This is returned if Read() has not been called, or the end of the
/// file has been reached.
///
None,
///
/// Start of a BAML document. This contains version information about the BAML.
///
StartDocument,
///
/// End of a BAML document
///
EndDocument,
///
/// Connection Id.
///
ConnectionId,
///
/// Start of an Element. An Element is any object that exists in
/// an object tree. This has a rough correspondance to Element nodes in XML
///
StartElement,
///
/// End of an Element.
///
EndElement,
///
/// A simple property of an Element. This can be a native property, attached
/// property, or XML specific properties such as namespaces
///
Property,
///
/// The content property of an Element.
///
ContentProperty,
///
/// A namespace property that defines prefix to namespace mappings in xml
///
XmlnsProperty,
///
/// The start of a compound property on an Element. This is used when the property value is
/// represented as a single string Value, but as an element tree.
///
StartComplexProperty,
///
/// The end of a compound property on an Element.
///
EndComplexProperty,
///
/// A section of literal content that is handled by an object
///
LiteralContent,
///
/// Text content of an element.
///
Text,
///
/// A RoutedEvent
///
RoutedEvent,
///
/// A non-routed, or normal CLR Event
///
Event,
///
/// A reference to a Resource that is included at this point in the BAML stream
///
IncludeReference,
///
/// A specific attribute or property in the reserved "Definition" namespace.
/// These attributes do not map to CLR properties or events, but are used
/// as processing directives.
///
DefAttribute,
///
/// A specific attribute or property in the reserved "PresentationOptions" namespace.
/// These attributes do not map to CLR properties or events, but are used
/// as processing directives.
///
PresentationOptionsAttribute,
///
/// A namespace mapping instruction used for including custom code and namespaces
///
PIMapping,
///
/// Start of a section that specifies a list of objects to be passed to the
/// element's constructor
///
StartConstructor,
///
/// End of a section that specifies a list of objects to be passed to the
/// element's constructor
///
EndConstructor
}
///
/// Reads BAML from a Stream and exposes an XmlReader-liker interface for BAML
///
//
// This code should always be transparent. Meaning you should never add
// SecurityCritical to this section of the code.
//
internal class BamlReader
{
#region Constructor
///
/// Create an instance of the BamlReader on the passed stream using
/// the passed ParserContext.
/// summary>
public BamlReader(Stream bamlStream)
{
_parserContext = new ParserContext();
_parserContext.XamlTypeMapper = XmlParserDefaults.DefaultMapper;
_bamlRecordReader = new BamlRecordReader(bamlStream, _parserContext, false);
_readState = ReadState.Initial;
_bamlNodeType = BamlNodeType.None;
_prefixDictionary = new XmlnsDictionary();
_value = string.Empty;
_assemblyName = string.Empty;
_prefix = string.Empty;
_xmlNamespace = string.Empty;
_clrNamespace = string.Empty;
_name = string.Empty;
_localName = string.Empty;
_ownerTypeName = string.Empty;
_properties = new ArrayList();
_haveUnprocessedRecord = false;
_deferableContentBlockDepth = -1;
_nodeStack = new Stack();
_reverseXmlnsTable = new Dictionary>();
}
#endregion Constructor
#region Public Methods
///
/// Return the number of properties. Note that this
/// does not include complex properties or children elements
///
public int PropertyCount
{
get { return _properties.Count; }
}
///
/// Return true if the current node has any simple properties
///
public bool HasProperties
{
get { return PropertyCount > 0; }
}
///
/// Return the connection Id of current element for hooking up
/// IDs and events.
///
public Int32 ConnectionId
{
get { return _connectionId; }
}
///
/// Defines what this attribute is used for such as being an alias for
/// xml:lang, xml:space or x:ID
///
public BamlAttributeUsage AttributeUsage
{
get { return _attributeUsage; }
}
///
/// Gets the type of the current node (eg Element, StartComplexProperty,
/// Text, etc)
///
public BamlNodeType NodeType
{
get { return _bamlNodeType; }
}
///
/// Gets the fully qualified name of the current node.
///
public string Name
{
get { return _name; }
}
///
/// Gets the local name only, with prefix and owning class removed
///
public string LocalName
{
get { return _localName; }
}
///
/// Gets the prefix associated with the current node, if there is one
///
//
// NOTE: Used by the localization tools via reflection.
//
public string Prefix
{
get { return _prefix; }
}
///
/// Gets the assembly name associated with the type of the current node, if there is one
///
public string AssemblyName
{
get { return _assemblyName; }
}
///
/// Gets the XML namespace URI of the node on which the reader is positioned
///
public string XmlNamespace
{
get { return _xmlNamespace; }
}
///
/// Gets the CLR namespace of the node on which the reader is positioned
///
public string ClrNamespace
{
get { return _clrNamespace; }
}
///
/// Gets the text value of the current node (eg property value or text content)
///
public string Value
{
get { return _value; }
}
public bool IsInjected
{
get { return _isInjected; }
}
// Whether this object instance is expected to be created via TypeConverter
public bool CreateUsingTypeConverter
{
get { return _useTypeConverter; }
}
public string TypeConverterName
{
get { return _typeConverterName; }
}
public string TypeConverterAssemblyName
{
get { return _typeConverterAssemblyName; }
}
///
/// Reads the next node from the stream.
///
public bool Read()
{
if (_readState == ReadState.EndOfFile ||
_readState == ReadState.Closed)
{
throw new InvalidOperationException(SR.Get(SRID.BamlReaderClosed));
}
ReadNextRecord();
return _readState != ReadState.EndOfFile;
}
private BamlNodeType NodeTypeInternal
{
set { _bamlNodeType = value; }
}
private void AddToPropertyInfoCollection(object info)
{
_properties.Add(info);
}
///
/// Close the underlying BAML stream.
///
///
/// Once the BamlReader is closed, it cannot be used
/// for any further operations. Calling any public interfaces will fail.
///
public void Close()
{
if (_readState != ReadState.Closed)
{
_bamlRecordReader.Close();
_currentBamlRecord = null;
_bamlRecordReader = null;
_readState = ReadState.Closed;
}
}
///
/// Moves to the first property for this element or object.
/// Return true if property exists, false otherwise.
///
public bool MoveToFirstProperty()
{
if (HasProperties)
{
_propertiesIndex = -1;
return MoveToNextProperty();
}
else
{
return false;
}
}
///
/// Move to the next property for this element or object.
/// Return true if there is a next property; false if there are no more properties.
///
public bool MoveToNextProperty()
{
if (_propertiesIndex < _properties.Count - 1)
{
_propertiesIndex++;
object obj = _properties[_propertiesIndex];
BamlPropertyInfo info = obj as BamlPropertyInfo;
if (info != null)
{
_name = info.Name;
_localName = info.LocalName;
int index = info.Name.LastIndexOf(".", StringComparison.Ordinal);
if (index > 0)
{
_ownerTypeName = info.Name.Substring(0, index);
}
else
{
// Eg. xmlns property
_ownerTypeName = string.Empty;
}
_value = info.Value;
_assemblyName = info.AssemblyName;
_prefix = info.Prefix;
_xmlNamespace = info.XmlNamespace;
_clrNamespace = info.ClrNamespace;
_connectionId = 0;
_contentPropertyName = string.Empty;
_attributeUsage = info.AttributeUsage;
// There are several node types for properties, but for now the only one that
// doesn't map to BamlNodeType.Property is xml namespace declarations.
if (info.RecordType == BamlRecordType.XmlnsProperty)
{
NodeTypeInternal = BamlNodeType.XmlnsProperty;
}
else if (info.RecordType == BamlRecordType.DefAttribute)
{
NodeTypeInternal = BamlNodeType.DefAttribute;
}
else if (info.RecordType == BamlRecordType.PresentationOptionsAttribute)
{
NodeTypeInternal = BamlNodeType.PresentationOptionsAttribute;
}
else
{
NodeTypeInternal = BamlNodeType.Property;
}
return true;
}
BamlContentPropertyInfo cpInfo = obj as BamlContentPropertyInfo;
if(null != cpInfo)
{
_contentPropertyName = cpInfo.LocalName;
_connectionId = 0;
_prefix = string.Empty;
_name = cpInfo.Name;
int index = cpInfo.Name.LastIndexOf(".", StringComparison.Ordinal);
if (index > 0)
{
_ownerTypeName = cpInfo.Name.Substring(0, index);
}
_localName = cpInfo.LocalName;
_ownerTypeName = string.Empty;
_assemblyName = cpInfo.AssemblyName;
_xmlNamespace = string.Empty;
_clrNamespace = string.Empty;
_attributeUsage = BamlAttributeUsage.Default;
_value = cpInfo.LocalName;
NodeTypeInternal = BamlNodeType.ContentProperty;
return true;
}
// Otherwise it must be a ConnectionId.
// Is there something we can Assert on for that?
_connectionId = (Int32)obj;
_contentPropertyName = string.Empty;
_prefix = string.Empty;
_name = string.Empty;
_localName = string.Empty;
_ownerTypeName = string.Empty;
_assemblyName = string.Empty;
_xmlNamespace = string.Empty;
_clrNamespace = string.Empty;
_attributeUsage = BamlAttributeUsage.Default;
_value = _connectionId.ToString(CultureInfo.CurrentCulture);
NodeTypeInternal = BamlNodeType.ConnectionId;
return true;
}
else
{
return false;
}
}
#endregion Public Methods
#region Internal Methods
///
/// Gets the next BamlRecord to be processed
///
private void GetNextRecord()
{
if (_currentStaticResourceRecords != null)
{
// Load the record from the front loaded static resource
_currentBamlRecord = _currentStaticResourceRecords[_currentStaticResourceRecordIndex++];
if (_currentStaticResourceRecordIndex == _currentStaticResourceRecords.Count)
{
// We are done with the records for this front loaded static resource
_currentStaticResourceRecords = null;
_currentStaticResourceRecordIndex = -1;
}
}
else
{
// Use the BamlRecord Reader to get the record
_currentBamlRecord = _bamlRecordReader.GetNextRecord();
}
}
/***************************************************************************\
*
* BamlReader.ReadNextRecord
*
* Read the next record, setting the ReadState, NodeType and other pertinent
* information about the record just read.
*
\***************************************************************************/
private void ReadNextRecord()
{
// If this is the first call to Read. Then read the Version Header.
if(_readState == ReadState.Initial)
{
_bamlRecordReader.ReadVersionHeader();
}
// We'll read in a loop until we get to a significant record. Note that Assembly,
// Type and Attribute records are read and processed, but the BamlReader never stops
// on one of these records, since they are not externally exposed.
bool keepOnReading = true;
while (keepOnReading)
{
// We may already have a record that was previously read in but not
// processed. This occurs when we've looped through all the properties
// on an element and have encountered a non-property record to stop
// the loop. In that case don't read another record and just process
// the one we have.
if (_haveUnprocessedRecord)
{
_haveUnprocessedRecord = false;
}
else
{
GetNextRecord();
}
// If the current baml record is null, then the stream is finished, closed
// or something else that prevents us reading further, so treat this
// as an end-of-file condition
if (_currentBamlRecord == null)
{
NodeTypeInternal = BamlNodeType.None;
_readState = ReadState.EndOfFile;
ClearProperties();
return;
}
// By default, the read state is interactive after a record has been read, and we
// should stop reading after this record is processed. This may be altered for
// specific record types.
_readState = ReadState.Interactive;
keepOnReading = false;
switch (_currentBamlRecord.RecordType)
{
// The following three records are internal to the BAMLReader and
// are not exposed publicly. They are used to update the map table
// that maps ids to assemblies, types and attributes.
case BamlRecordType.AssemblyInfo:
ReadAssemblyInfoRecord();
keepOnReading = true;
break;
case BamlRecordType.TypeInfo:
case BamlRecordType.TypeSerializerInfo:
MapTable.LoadTypeInfoRecord((BamlTypeInfoRecord)_currentBamlRecord);
keepOnReading = true;
break;
case BamlRecordType.AttributeInfo:
MapTable.LoadAttributeInfoRecord((BamlAttributeInfoRecord)_currentBamlRecord);
keepOnReading = true;
break;
case BamlRecordType.StringInfo:
MapTable.LoadStringInfoRecord((BamlStringInfoRecord)_currentBamlRecord);
keepOnReading = true;
break;
case BamlRecordType.ContentProperty:
// This is just a cache of meta-data, no visible effect.
ReadContentPropertyRecord();
keepOnReading = true;
break;
// The following records are publically exposed
case BamlRecordType.DocumentStart:
ReadDocumentStartRecord();
break;
case BamlRecordType.DocumentEnd:
ReadDocumentEndRecord();
break;
case BamlRecordType.PIMapping:
ReadPIMappingRecord();
break;
case BamlRecordType.LiteralContent:
ReadLiteralContentRecord();
break;
case BamlRecordType.ElementStart:
case BamlRecordType.StaticResourceStart:
ReadElementStartRecord();
break;
case BamlRecordType.ElementEnd:
case BamlRecordType.StaticResourceEnd:
ReadElementEndRecord();
break;
case BamlRecordType.PropertyComplexStart:
case BamlRecordType.PropertyArrayStart:
case BamlRecordType.PropertyIListStart:
case BamlRecordType.PropertyIDictionaryStart:
ReadPropertyComplexStartRecord();
break;
case BamlRecordType.PropertyComplexEnd:
case BamlRecordType.PropertyArrayEnd:
case BamlRecordType.PropertyIListEnd:
case BamlRecordType.PropertyIDictionaryEnd:
ReadPropertyComplexEndRecord();
break;
case BamlRecordType.Text:
case BamlRecordType.TextWithId:
case BamlRecordType.TextWithConverter:
ReadTextRecord();
break;
case BamlRecordType.DeferableContentStart:
ReadDeferableContentRecord();
keepOnReading = true;
break;
case BamlRecordType.ConstructorParametersStart:
ReadConstructorStart();
break;
case BamlRecordType.ConstructorParametersEnd:
ReadConstructorEnd();
break;
case BamlRecordType.ConnectionId:
ReadConnectionIdRecord();
break;
case BamlRecordType.StaticResourceId:
ReadStaticResourceId();
keepOnReading = true;
break;
default:
// Can't have any other type of record at this point.
throw new InvalidOperationException(SR.Get(SRID.ParserUnknownBaml,
((int)_currentBamlRecord.RecordType).ToString(CultureInfo.CurrentCulture)));
}
}
}
/***************************************************************************\
*
* BamlReader.ReadProperties
*
* This is called when an element start has been encountered (or something
* similar) and a number of properties may or may not follow. Read all the
* properties, storing them in the _properties arraylist. When a non-property
* record is encountered, stop, but store that record as the
* _currentBamlRecord.
*
\***************************************************************************/
private void ReadProperties()
{
// Keep reading records until we get one that is not processed
while (!_haveUnprocessedRecord)
{
GetNextRecord();
ProcessPropertyRecord();
}
}
/***************************************************************************\
*
* BamlReader.ProcessPropertyRecord
*
* This is called we assume we have a record that is an attribute in the start
* tag of an xml element. It is processed here. If we encounter something
* that is not a 'property', then set the _haveUnprocessedRecord flag.
*
\***************************************************************************/
private void ProcessPropertyRecord()
{
switch (_currentBamlRecord.RecordType)
{
// The following five records are internal to the BAMLReader and
// are not exposed publicly. They are used to update the map table
// that maps ids to assemblies, types and attributes.
case BamlRecordType.AssemblyInfo:
ReadAssemblyInfoRecord();
break;
case BamlRecordType.TypeInfo:
case BamlRecordType.TypeSerializerInfo:
MapTable.LoadTypeInfoRecord((BamlTypeInfoRecord)_currentBamlRecord);
break;
case BamlRecordType.AttributeInfo:
MapTable.LoadAttributeInfoRecord((BamlAttributeInfoRecord)_currentBamlRecord);
break;
case BamlRecordType.StringInfo:
MapTable.LoadStringInfoRecord((BamlStringInfoRecord)_currentBamlRecord);
break;
// The following records are property-like
case BamlRecordType.XmlnsProperty:
ReadXmlnsPropertyRecord();
break;
case BamlRecordType.ConnectionId:
ReadConnectionIdRecord();
break;
case BamlRecordType.Property:
case BamlRecordType.PropertyWithConverter:
ReadPropertyRecord();
break;
case BamlRecordType.ContentProperty:
// This is just a cache of meta-data, no visible effect.
ReadContentPropertyRecord();
break;
case BamlRecordType.PropertyStringReference:
ReadPropertyStringRecord();
break;
case BamlRecordType.PropertyTypeReference:
ReadPropertyTypeRecord();
break;
case BamlRecordType.PropertyWithExtension:
ReadPropertyWithExtensionRecord();
break;
case BamlRecordType.PropertyWithStaticResourceId:
ReadPropertyWithStaticResourceIdRecord();
break;
case BamlRecordType.PropertyCustom:
ReadPropertyCustomRecord();
break;
case BamlRecordType.DefAttribute:
ReadDefAttributeRecord();
break;
case BamlRecordType.PresentationOptionsAttribute:
ReadPresentationOptionsAttributeRecord();
break;
case BamlRecordType.DefAttributeKeyType:
ReadDefAttributeKeyTypeRecord();
break;
case BamlRecordType.RoutedEvent:
ReadRoutedEventRecord();
break;
case BamlRecordType.ClrEvent:
ReadClrEventRecord();
break;
case BamlRecordType.KeyElementStart:
{
// Process the subtree that is stored as part of a key tree and
// translate this back into a compact MarkupExtension string that
// is represented as a x:Key="something"
BamlKeyInfo info = ProcessKeyTree();
AddToPropertyInfoCollection(info);
}
break;
// Any other record types are not processed here
default:
_haveUnprocessedRecord = true;
break;
}
}
/****************************************************************************\
*
* BamlReader.ReadXmlnsPropertyRecord
*
* Read the namespace record and update the namespace dictionary with the
* key being the namespace prefix and the value being the namespace string.
* Note that Xmlns properties are not the same as regular properties, since
* prefix, xmlnamespace, clrnamespace and name have quite different meanings.
*
\***************************************************************************/
private void ReadXmlnsPropertyRecord()
{
BamlXmlnsPropertyRecord bamlRecord = (BamlXmlnsPropertyRecord)_currentBamlRecord;
_parserContext.XmlnsDictionary[bamlRecord.Prefix] = bamlRecord.XmlNamespace;
_prefixDictionary[bamlRecord.XmlNamespace] = bamlRecord.Prefix;
BamlPropertyInfo info = new BamlPropertyInfo();
info.Value = bamlRecord.XmlNamespace;
info.XmlNamespace = string.Empty;
info.ClrNamespace = string.Empty;
info.AssemblyName = string.Empty;
info.Prefix = "xmlns";
info.LocalName = bamlRecord.Prefix == null ? string.Empty : bamlRecord.Prefix;
info.Name = (bamlRecord.Prefix == null || bamlRecord.Prefix == string.Empty) ?
"xmlns" :
"xmlns:" + bamlRecord.Prefix;
info.RecordType = BamlRecordType.XmlnsProperty;
AddToPropertyInfoCollection(info);
}
/***************************************************************************\
*
* BamlReader.ReadPropertyRecord
*
* Read the property record and store the pertinent contents in the
* _properties array list.
*
\***************************************************************************/
private void ReadPropertyRecord()
{
string value = ((BamlPropertyRecord)_currentBamlRecord).Value;
// Escape the text as necessary to avoid being mistaken for a MarkupExtension.
value = MarkupExtensionParser.AddEscapeToLiteralString(value);
AddToPropertyInfoCollection(ReadPropertyRecordCore(value));
}
private void ReadContentPropertyRecord()
{
BamlContentPropertyInfo cpInfo = new BamlContentPropertyInfo();
BamlContentPropertyRecord bamlRecord = (BamlContentPropertyRecord)_currentBamlRecord;
SetCommonPropertyInfo(cpInfo, bamlRecord.AttributeId);
cpInfo.RecordType = _currentBamlRecord.RecordType;
AddToPropertyInfoCollection(cpInfo);
}
/****************************************************************************\
*
* BamlReader.ReadPropertyStringRecord
*
* Read the property record and store the pertinent contents in the
* _properties array list.
*
\***************************************************************************/
private void ReadPropertyStringRecord()
{
string value = MapTable.GetStringFromStringId(((BamlPropertyStringReferenceRecord)_currentBamlRecord).StringId);
AddToPropertyInfoCollection(ReadPropertyRecordCore(value));
}
/****************************************************************************\
*
* BamlReader.ReadPropertyTypeRecord
*
* Read the property record and store the pertinent contents in the
* _properties array list. Convert the TypeId into a fully qualified type
* name.
*
\***************************************************************************/
private void ReadPropertyTypeRecord()
{
BamlPropertyInfo info = new BamlPropertyInfo();
SetCommonPropertyInfo(info,
((BamlPropertyTypeReferenceRecord)_currentBamlRecord).AttributeId);
info.RecordType = _currentBamlRecord.RecordType;
info.Value = GetTypeValueString(((BamlPropertyTypeReferenceRecord)_currentBamlRecord).TypeId);
info.AttributeUsage = BamlAttributeUsage.Default;
AddToPropertyInfoCollection(info);
}
private void ReadPropertyWithExtensionRecord()
{
BamlPropertyInfo info = new BamlPropertyInfo();
SetCommonPropertyInfo(info, ((BamlPropertyWithExtensionRecord)_currentBamlRecord).AttributeId);
info.RecordType = _currentBamlRecord.RecordType;
info.Value = GetExtensionValueString((IOptimizedMarkupExtension)_currentBamlRecord);
info.AttributeUsage = BamlAttributeUsage.Default;
AddToPropertyInfoCollection(info);
}
private void ReadPropertyWithStaticResourceIdRecord()
{
BamlPropertyWithStaticResourceIdRecord bamlPropertyWithStaticResourceIdRecord =
(BamlPropertyWithStaticResourceIdRecord)_currentBamlRecord;
BamlPropertyInfo info = new BamlPropertyInfo();
SetCommonPropertyInfo(info, bamlPropertyWithStaticResourceIdRecord.AttributeId);
info.RecordType = _currentBamlRecord.RecordType;
BamlOptimizedStaticResourceRecord optimizedStaticResourceRecord =
(BamlOptimizedStaticResourceRecord)_currentKeyInfo.StaticResources[bamlPropertyWithStaticResourceIdRecord.StaticResourceId][0];
info.Value = GetExtensionValueString((IOptimizedMarkupExtension)optimizedStaticResourceRecord);
info.AttributeUsage = BamlAttributeUsage.Default;
AddToPropertyInfoCollection(info);
}
/***************************************************************************\
*
* BamlReader.ReadPropertyRecordCore
*
* Read the property record and return the pertinent contents in a
* BamlPropertyInfo record.
*
\***************************************************************************/
private BamlPropertyInfo ReadPropertyRecordCore(string value)
{
BamlPropertyInfo info = new BamlPropertyInfo();
SetCommonPropertyInfo(info,
((BamlPropertyRecord)_currentBamlRecord).AttributeId);
info.RecordType = _currentBamlRecord.RecordType;
info.Value = value;
return info;
}
/****************************************************************************\
*
* BamlReader.ReadPropertyCustomRecord
*
* Read the custom property record and store the pertinent contents in the
* _properties array list. This involves reversing the binary representation
* of the data back into a string using the TypeConverter for the
* property type.
*
\***************************************************************************/
private void ReadPropertyCustomRecord()
{
BamlPropertyInfo info = GetPropertyCustomRecordInfo();
AddToPropertyInfoCollection(info);
}
private BamlPropertyInfo GetPropertyCustomRecordInfo()
{
BamlPropertyInfo info = new BamlPropertyInfo();
BamlAttributeInfoRecord attrInfo = SetCommonPropertyInfo(info,
((BamlPropertyCustomRecord)_currentBamlRecord).AttributeId);
info.RecordType = _currentBamlRecord.RecordType;
info.AttributeUsage = BamlAttributeUsage.Default;
BamlPropertyCustomRecord bamlRecord = (BamlPropertyCustomRecord)_currentBamlRecord;
// Reverse the binary data stored in the record into a string by first getting the
// property. If it has not already been cached in the attribute info record, then
// attempt to resolve it as a DependencyProperty or a PropertyInfo.
if (attrInfo.DP == null && attrInfo.PropInfo == null)
{
attrInfo.DP = MapTable.GetDependencyProperty(attrInfo);
if (attrInfo.OwnerType == null)
{
throw new InvalidOperationException(SR.Get(SRID.BamlReaderNoOwnerType, attrInfo.Name, AssemblyName));
}
if (attrInfo.DP == null)
{
attrInfo.PropInfo = attrInfo.OwnerType.GetProperty(attrInfo.Name,
BindingFlags.Instance | BindingFlags.Public);
if (attrInfo.PropInfo == null)
{
throw new InvalidOperationException(SR.Get(SRID.ParserCantGetDPOrPi, info.Name));
}
}
}
// If we have a property, then get its type and call GetCustomValue,
// which uses the XamlSerializer to turn the binary data into a
// real object
Type propertyType = attrInfo.GetPropertyType();
string propertyName = attrInfo.Name;
short sid = bamlRecord.SerializerTypeId;
// if a Setter of Trigger's Property property is being set, then its value is always
// a DP. Get the attribInfo of this DP property from the ValueId read into the custom
// property record and resolve it into an actual DP instance.
if (sid == (short)KnownElements.DependencyPropertyConverter)
{
Type declaringType = null;
_propertyDP = _bamlRecordReader.GetCustomDependencyPropertyValue(bamlRecord, out declaringType);
declaringType = declaringType == null ? _propertyDP.OwnerType : declaringType;
info.Value = declaringType.Name + "." + _propertyDP.Name;
string xmlns = _parserContext.XamlTypeMapper.GetXmlNamespace(declaringType.Namespace,
declaringType.Assembly.FullName);
string prefix = GetXmlnsPrefix(xmlns);
if (prefix != string.Empty)
{
info.Value = prefix + ":" + info.Value;
}
if (!_propertyDP.PropertyType.IsEnum)
{
_propertyDP = null;
}
}
else
{
if (_propertyDP != null)
{
propertyType = _propertyDP.PropertyType;
propertyName = _propertyDP.Name;
_propertyDP = null;
}
object value = _bamlRecordReader.GetCustomValue(bamlRecord, propertyType, propertyName);
// Once we have a real object, turn that back into a string, and store this
// as the value for this property
TypeConverter converter = TypeDescriptor.GetConverter(value.GetType());
info.Value = converter.ConvertToString(null,
TypeConverterHelper.InvariantEnglishUS,
value);
}
return info;
}
/***************************************************************************\
*
* BamlReader.ReadDefAttributeRecord
*
* Read a x: record that contains the object to use as a key when inserting
* the current element into a dictionary.
*
\***************************************************************************/
private void ReadDefAttributeRecord()
{
BamlDefAttributeRecord bamlRecord = (BamlDefAttributeRecord)_currentBamlRecord;
bamlRecord.Name = MapTable.GetStringFromStringId(bamlRecord.NameId);
BamlPropertyInfo info = new BamlPropertyInfo();
info.Value = bamlRecord.Value;
info.AssemblyName = string.Empty;
info.Prefix = (string)_prefixDictionary[XamlReaderHelper.DefinitionNamespaceURI];
info.XmlNamespace = XamlReaderHelper.DefinitionNamespaceURI;
info.ClrNamespace = string.Empty;
info.Name = bamlRecord.Name;
info.LocalName = info.Name;
info.RecordType = BamlRecordType.DefAttribute;
AddToPropertyInfoCollection(info);
}
/***************************************************************************\
*
* BamlReader.ReadPresentationOptionsAttributeRecord
*
* Read a PresentationsOptions: record used for WPF-specific
* parsing options (e.g., PresentationOptions:Freeze).
*
\***************************************************************************/
private void ReadPresentationOptionsAttributeRecord()
{
BamlPresentationOptionsAttributeRecord bamlRecord = (BamlPresentationOptionsAttributeRecord)_currentBamlRecord;
bamlRecord.Name = MapTable.GetStringFromStringId(bamlRecord.NameId);
BamlPropertyInfo info = new BamlPropertyInfo();
info.Value = bamlRecord.Value;
info.AssemblyName = string.Empty;
info.Prefix = (string)_prefixDictionary[XamlReaderHelper.PresentationOptionsNamespaceURI];
info.XmlNamespace = XamlReaderHelper.PresentationOptionsNamespaceURI;
info.ClrNamespace = string.Empty;
info.Name = bamlRecord.Name;
info.LocalName = info.Name;
info.RecordType = BamlRecordType.PresentationOptionsAttribute;
AddToPropertyInfoCollection(info);
}
/***************************************************************************\
*
* BamlReader.ReadDefAttributeKeyTypeRecord
*
* Read a x: record that contains the object to use as a key when inserting
* the current element into a dictionary.
*
\***************************************************************************/
private void ReadDefAttributeKeyTypeRecord()
{
BamlDefAttributeKeyTypeRecord bamlRecord = (BamlDefAttributeKeyTypeRecord)_currentBamlRecord;
BamlPropertyInfo info = new BamlPropertyInfo();
info.Value = GetTypeValueString(bamlRecord.TypeId);
info.AssemblyName = string.Empty;
info.Prefix = (string)_prefixDictionary[XamlReaderHelper.DefinitionNamespaceURI];
info.XmlNamespace = XamlReaderHelper.DefinitionNamespaceURI;
info.ClrNamespace = string.Empty;
info.Name = XamlReaderHelper.DefinitionName;
info.LocalName = info.Name;
info.RecordType = BamlRecordType.DefAttribute;
AddToPropertyInfoCollection(info);
}
/****************************************************************************\
*
* BamlReader.ReadDeferableContentRecord
*
* Read defered content section of a baml file. Note that this is written
* to baml with the following format:
* BamlDeferableContentStartRecord
* BamlDefAttributeKeyString/Type records, one for each value
* BamlElementStartRecord, one for each value
* BamlRecords within the element
* BamlElementEndRecord
*
* This is presented to the user like a 'normal' dictionary, so here is
* what the user should see:
* ElementStart for the dictionary
* ElementStart, one for each value
* DictionaryKey record, one for each value
* Records within the element
* ElementEnd
* ElementEnd for the dictionary
*
* To do this, queue up the entire contents of the Deferable block and
* re-arrange the records.
*
\***************************************************************************/
private void ReadDeferableContentRecord()
{
_deferableContentBlockDepth = _nodeStack.Count;
// The start of a block of deferable content has been reached. Build
// a key table that will be inserted into the Values as they are loaded.
_deferableContentPosition = ReadDeferKeys();
}
/***************************************************************************\
*
* BamlReader.ReadDeferKeys
*
* Read the keys in a defered content section, and build a table that holds
* these records. These keys are automagically inserted into the outer level
* value start element records to make it look like a x:Key attribute.
* Return the baml stream position for the end of the key section to which
* all key offsets are relative
*
\***************************************************************************/
private Int64 ReadDeferKeys()
{
// Keep reading records until we get one that is not processed
Int64 endOfDefKeys = -1;
_deferKeys = new List();
while (!_haveUnprocessedRecord)
{
GetNextRecord();
ProcessDeferKey();
if (!_haveUnprocessedRecord)
{
endOfDefKeys = _bamlRecordReader.StreamPosition;
}
}
return endOfDefKeys;
}
/****************************************************************************\
*
* BamlReader.ProcessDeferKey
*
* Read a single baml record. If it is a defer key, add it to the table of
* keys. If we encounter something that is not a 'key', then set the
*_haveUnprocessedRecord flag.
*
\***************************************************************************/
private void ProcessDeferKey()
{
switch (_currentBamlRecord.RecordType)
{
// The following three records are internal to the BAMLReader and
// are not exposed publicly. They are used to update the map table
// that maps ids to assemblies, types and attributes.
case BamlRecordType.DefAttributeKeyString:
BamlDefAttributeKeyStringRecord stringKeyRecord = _currentBamlRecord as BamlDefAttributeKeyStringRecord;
if (stringKeyRecord != null)
{
BamlKeyInfo info;
// The "Shared"ness is stored in the BAML with the Key
// But at the XAML level it is a sibling attribute of the key.
info = CheckForSharedness();
if (null != info)
_deferKeys.Add(info);
// Get the value string from the string table, and cache it in the
// record.
stringKeyRecord.Value = MapTable.GetStringFromStringId(
stringKeyRecord.ValueId);
// Add information to the key list to indicate we have a x:Key
// attribute
info = new BamlKeyInfo();
info.Value = stringKeyRecord.Value;
info.AssemblyName = string.Empty;
info.Prefix = (string)_prefixDictionary[XamlReaderHelper.DefinitionNamespaceURI];
info.XmlNamespace = XamlReaderHelper.DefinitionNamespaceURI;
info.ClrNamespace = string.Empty;
info.Name = XamlReaderHelper.DefinitionName;
info.LocalName = info.Name;
info.RecordType = BamlRecordType.DefAttribute;
info.Offset = ((IBamlDictionaryKey)stringKeyRecord).ValuePosition;
_deferKeys.Add(info);
}
break;
case BamlRecordType.DefAttributeKeyType:
BamlDefAttributeKeyTypeRecord typeKeyRecord = _currentBamlRecord as BamlDefAttributeKeyTypeRecord;
if (typeKeyRecord != null)
{
// Translate the type information held in the baml record into
// the {x:Type prefix:Classname} format that would be used on
// a x:Key attribute.
string typeExtensionPrefix = (string)_prefixDictionary[XamlReaderHelper.DefinitionNamespaceURI];
string typeExtensionName;
if (typeExtensionPrefix != string.Empty)
{
typeExtensionName = "{" + typeExtensionPrefix + ":Type ";
}
else
{
typeExtensionName = "{Type ";
}
BamlTypeInfoRecord typeInfo = MapTable.GetTypeInfoFromId(typeKeyRecord.TypeId);
string typeName = typeInfo.TypeFullName;
typeName = typeName.Substring(typeName.LastIndexOf(".", StringComparison.Ordinal) + 1);
string assemblyName;
string prefix;
string xmlNamespace;
GetAssemblyAndPrefixAndXmlns(typeInfo, out assemblyName, out prefix, out xmlNamespace);
if (prefix != string.Empty)
{
typeName = typeExtensionName + prefix + ":" + typeName + "}";
}
else
{
typeName = typeExtensionName + typeName + "}";
}
// Add information to the key list to indicate we have a x:Key
// attribute
BamlKeyInfo info = new BamlKeyInfo();
info.Value = typeName;
info.AssemblyName = string.Empty;
info.Prefix = typeExtensionPrefix;
info.XmlNamespace = XamlReaderHelper.DefinitionNamespaceURI;
info.ClrNamespace = string.Empty;
info.Name = XamlReaderHelper.DefinitionName;
info.LocalName = info.Name;
info.RecordType = BamlRecordType.DefAttribute;
info.Offset = ((IBamlDictionaryKey)typeKeyRecord).ValuePosition;
_deferKeys.Add(info);
}
break;
case BamlRecordType.KeyElementStart:
{
BamlKeyInfo info;
// The "Shared"ness is stored in the BAML with the Key
// But at the XAML level it is a sibling attribute of the key.
info = CheckForSharedness();
if(null != info)
_deferKeys.Add(info);
// Process the subtree that is stored as part of a key tree and
// translate this back into a compact MarkupExtension string.
// Add information to the key list to indicate we have a x:Key
// with a MarkupExtension
info = ProcessKeyTree();
_deferKeys.Add(info);
}
break;
case BamlRecordType.StaticResourceStart:
case BamlRecordType.OptimizedStaticResource:
{
// Process the subtree stored as part of a StaticResource
List srRecords = new List();
// This is for the start record
_currentBamlRecord.Pin();
srRecords.Add(_currentBamlRecord);
// Note that BamlOptmizedStaticResourceRecord is a singleton record
if (_currentBamlRecord.RecordType == BamlRecordType.StaticResourceStart)
{
// Process the subtree that is stored as part of this static resource
ProcessStaticResourceTree(srRecords);
}
// Add the current StaticResource record to the list of StaticResources held per key
BamlKeyInfo keyInfo = _deferKeys[_deferKeys.Count-1];
keyInfo.StaticResources.Add(srRecords);
}
break;
// Any other record types are not processed here
default:
_haveUnprocessedRecord = true;
break;
}
}
private BamlKeyInfo CheckForSharedness()
{
IBamlDictionaryKey dictKey = (IBamlDictionaryKey)_currentBamlRecord;
Debug.Assert(dictKey != null, "Bad Key record");
if (!dictKey.SharedSet)
return null;
BamlKeyInfo info = new BamlKeyInfo();
info.Value = dictKey.Shared.ToString();
info.AssemblyName = string.Empty;
info.Prefix = (string)_prefixDictionary[XamlReaderHelper.DefinitionNamespaceURI];
info.XmlNamespace = XamlReaderHelper.DefinitionNamespaceURI;
info.ClrNamespace = string.Empty;
info.Name = XamlReaderHelper.DefinitionShared;
info.LocalName = info.Name;
info.RecordType = BamlRecordType.DefAttribute;
info.Offset = dictKey.ValuePosition;
return info;
}
/****************************************************************************\
*
* BamlReader.ProcessKeyTree
*
* Read a tree of baml records that make up a dictionary key and translate them
* back in the compact syntax representation of a MarkupExtension section.
* When we encounter KeyElementEnd record, then stop.
*
\***************************************************************************/
private BamlKeyInfo ProcessKeyTree()
{
BamlKeyElementStartRecord keyStartRecord = _currentBamlRecord as BamlKeyElementStartRecord;
Debug.Assert(keyStartRecord != null, "Bad Key Element Start record");
// Translate the type information held in the baml record into
// the "{prefix:Classname " format that would be used on
// a x:Key attribute.
BamlTypeInfoRecord typeInfo = MapTable.GetTypeInfoFromId(keyStartRecord.TypeId);
string markupString = typeInfo.TypeFullName;
markupString = markupString.Substring(markupString.LastIndexOf(".", StringComparison.Ordinal) + 1);
string assemblyName;
string prefix;
string xmlNamespace;
GetAssemblyAndPrefixAndXmlns(typeInfo, out assemblyName, out prefix, out xmlNamespace);
if (prefix != string.Empty)
{
markupString = "{" + prefix + ":" + markupString + " ";
}
else
{
markupString = "{" + markupString + " ";
}
bool notDone = true;
BamlNodeInfo nodeInfo;
// Keep track of whether we have written a property or not at a given nesting
// level so that we know when to add commas between properties. Also keep
// track of when we have entered a constructor parameter section and when
// we have written out the first parameter to handle adding commas between
// constructor parameters.
Stack readProperty = new Stack();
Stack readConstructor = new Stack();
Stack readFirstConstructor = new Stack();
readProperty.Push(false); // Property has not yet been read
readConstructor.Push(false); // Constructor section has not been read
readFirstConstructor.Push(false); // First constructor parameter has not been read
while (notDone)
{
// Read the next record. Some of the processing below reads ahead one
// record and sets _haveUnprocessedRecord to true, in which case we
// don't want to read another one.
if (!_haveUnprocessedRecord)
{
GetNextRecord();
}
else
{
_haveUnprocessedRecord = false;
}
switch (_currentBamlRecord.RecordType)
{
// The following five records are internal to the BAMLReader and
// are not exposed publicly. They are used to update the map table
// that maps ids to assemblies, types and attributes.
case BamlRecordType.AssemblyInfo:
ReadAssemblyInfoRecord();
break;
case BamlRecordType.TypeInfo:
case BamlRecordType.TypeSerializerInfo:
MapTable.LoadTypeInfoRecord((BamlTypeInfoRecord)_currentBamlRecord);
break;
case BamlRecordType.AttributeInfo:
MapTable.LoadAttributeInfoRecord((BamlAttributeInfoRecord)_currentBamlRecord);
break;
case BamlRecordType.StringInfo:
MapTable.LoadStringInfoRecord((BamlStringInfoRecord)_currentBamlRecord);
break;
case BamlRecordType.PropertyComplexStart:
ReadPropertyComplexStartRecord();
nodeInfo = (BamlNodeInfo)_nodeStack.Pop();
if ((bool)readProperty.Pop())
{
markupString += ", ";
}
markupString += nodeInfo.LocalName + "=";
readProperty.Push(true);
break;
case BamlRecordType.PropertyComplexEnd:
break;
case BamlRecordType.Text:
case BamlRecordType.TextWithId:
BamlTextWithIdRecord textWithIdRecord = _currentBamlRecord as BamlTextWithIdRecord;
if (textWithIdRecord != null)
{
// Get the value string from the string table, and cache it in the
// record.
textWithIdRecord.Value = MapTable.GetStringFromStringId(
textWithIdRecord.ValueId);
}
// If the text contains '{' or '}' then we have to escape these
// so that it won't be interpreted as a MarkupExtension
string escapedString = EscapeString(((BamlTextRecord)_currentBamlRecord).Value);
if ((bool)readFirstConstructor.Peek())
{
markupString += ", ";
}
markupString += escapedString;
if ((bool)readConstructor.Peek())
{
readFirstConstructor.Pop();
readFirstConstructor.Push(true);
}
break;
case BamlRecordType.ElementStart:
// Process commas between constructor parameters
if ((bool)readFirstConstructor.Peek())
{
markupString += ", ";
}
if ((bool)readConstructor.Peek())
{
readFirstConstructor.Pop();
readFirstConstructor.Push(true);
}
// Setup for the next level
readProperty.Push(false);
readConstructor.Push(false);
readFirstConstructor.Push(false);
// Write element type. Translate the type information held in the
// baml record into the "prefix:Classname" format
BamlElementStartRecord elementStartRecord = _currentBamlRecord as BamlElementStartRecord;
BamlTypeInfoRecord elementTypeInfo = MapTable.GetTypeInfoFromId(elementStartRecord.TypeId);
string typename = elementTypeInfo.TypeFullName;
typename = typename.Substring(typename.LastIndexOf(".", StringComparison.Ordinal) + 1);
GetAssemblyAndPrefixAndXmlns(elementTypeInfo, out assemblyName, out prefix, out xmlNamespace);
if (prefix != string.Empty)
{
markupString += "{" + prefix + ":" + typename + " ";
}
else
{
markupString = "{" + typename + " ";
}
break;
case BamlRecordType.ElementEnd:
readProperty.Pop();
readConstructor.Pop();
readFirstConstructor.Pop();
markupString += "}";
break;
case BamlRecordType.ConstructorParametersStart:
readConstructor.Pop();
readConstructor.Push(true);
break;
case BamlRecordType.ConstructorParametersEnd:
readConstructor.Pop();
readConstructor.Push(false);
readFirstConstructor.Pop();
readFirstConstructor.Push(false);
break;
case BamlRecordType.ConstructorParameterType:
// Process commas between constructor parameters
if ((bool)readFirstConstructor.Peek())
{
markupString += ", ";
}
if ((bool)readConstructor.Peek())
{
readFirstConstructor.Pop();
readFirstConstructor.Push(true);
}
BamlConstructorParameterTypeRecord constTypeRecord = _currentBamlRecord as BamlConstructorParameterTypeRecord;
markupString += GetTypeValueString(constTypeRecord.TypeId);
break;
case BamlRecordType.Property:
case BamlRecordType.PropertyWithConverter:
{
string value = ((BamlPropertyRecord)_currentBamlRecord).Value;
BamlPropertyInfo propertyInfo = ReadPropertyRecordCore(value);
if ((bool)readProperty.Pop())
{
markupString += ", ";
}
markupString += propertyInfo.LocalName + "=" + propertyInfo.Value;
readProperty.Push(true);
}
break;
case BamlRecordType.PropertyCustom:
{
BamlPropertyInfo propertyInfo = GetPropertyCustomRecordInfo();
if ((bool)readProperty.Pop())
{
markupString += ", ";
}
markupString += propertyInfo.LocalName + "=" + propertyInfo.Value;
readProperty.Push(true);
}
break;
case BamlRecordType.PropertyStringReference:
{
string value = MapTable.GetStringFromStringId(((BamlPropertyStringReferenceRecord)_currentBamlRecord).StringId);
BamlPropertyInfo propertyInfo = ReadPropertyRecordCore(value);
if ((bool)readProperty.Pop())
{
markupString += ", ";
}
markupString += propertyInfo.LocalName + "=" + propertyInfo.Value;
readProperty.Push(true);
}
break;
case BamlRecordType.PropertyTypeReference:
{
string value = GetTypeValueString(((BamlPropertyTypeReferenceRecord)_currentBamlRecord).TypeId);
string attributeName = MapTable.GetAttributeNameFromId(
((BamlPropertyTypeReferenceRecord)_currentBamlRecord).AttributeId);
if ((bool)readProperty.Pop())
{
markupString += ", ";
}
markupString += attributeName + "=" + value;
readProperty.Push(true);
}
break;
case BamlRecordType.PropertyWithExtension:
{
string value = GetExtensionValueString((BamlPropertyWithExtensionRecord)_currentBamlRecord);
string attributeName = MapTable.GetAttributeNameFromId(
((BamlPropertyWithExtensionRecord)_currentBamlRecord).AttributeId);
if ((bool)readProperty.Pop())
{
markupString += ", ";
}
markupString += attributeName + "=" + value;
readProperty.Push(true);
}
break;
case BamlRecordType.KeyElementEnd:
markupString += "}";
notDone = false;
_haveUnprocessedRecord = false;
break;
default:
// Can't have any other type of record at this point.
throw new InvalidOperationException(SR.Get(SRID.ParserUnknownBaml,
((int)_currentBamlRecord.RecordType).ToString(CultureInfo.CurrentCulture)));
}
}
// At this point the markup string representing the MarkupExtension should
// be complete, so set this as the value for this key.
BamlKeyInfo info = new BamlKeyInfo();
info.Value = markupString;
info.AssemblyName = string.Empty;
info.Prefix = (string)_prefixDictionary[XamlReaderHelper.DefinitionNamespaceURI];
info.XmlNamespace = XamlReaderHelper.DefinitionNamespaceURI;
info.ClrNamespace = string.Empty;
info.Name = XamlReaderHelper.DefinitionName;
info.LocalName = info.Name;
info.RecordType = BamlRecordType.DefAttribute;
info.Offset = ((IBamlDictionaryKey)keyStartRecord).ValuePosition;
return info;
}
///
/// Picks up all the BamlRecords for a front loaded static resource into a
/// list of BamlRecords.
///
private void ProcessStaticResourceTree(List srRecords)
{
bool notDone = true;
while (notDone)
{
// We may already have a record that was previously read in but not
// processed. This occurs when we've looped through all the properties
// on an element and have encountered a non-property record to stop
// the loop. In that case don't read another record and just process
// the one we have.
if (_haveUnprocessedRecord)
{
_haveUnprocessedRecord = false;
}
else
{
GetNextRecord();
}
// Remember the BamlRecords beloning to this StaticResource
_currentBamlRecord.Pin();
srRecords.Add(_currentBamlRecord);
if (_currentBamlRecord.RecordType == BamlRecordType.StaticResourceEnd)
{
notDone = false;
}
}
}
///
/// Picks up the list of BamlRecords in the deferred
/// section corresponding to this StaticResourceId
///
private void ReadStaticResourceId()
{
BamlStaticResourceIdRecord bamlRecord = (BamlStaticResourceIdRecord)_currentBamlRecord;
_currentStaticResourceRecords = _currentKeyInfo.StaticResources[bamlRecord.StaticResourceId];
_currentStaticResourceRecordIndex = 0;
}
/***************************************************************************\
*
* BamlReader.EscapeString
*
* Check for '{' and '}' and escape any that are found in the passed value.
* Don't create a new string unless you have to.
*
\***************************************************************************/
private string EscapeString(string value)
{
StringBuilder builder = null;
for (int i=0; i 0)
{
_ownerTypeName = nodeInfo.Name.Substring(0, index);
}
else
{
// Eg. xmlns property
_ownerTypeName = string.Empty;
}
_name = nodeInfo.Name;
_clrNamespace = nodeInfo.ClrNamespace;
_assemblyName = nodeInfo.AssemblyName;
_prefix = nodeInfo.Prefix;
_xmlNamespace = nodeInfo.XmlNamespace;
nodeInfo.RecordType = _currentBamlRecord.RecordType;
_nodeStack.Push(nodeInfo);
// Read the properties that may be part of the start tag
ReadProperties();
}
/****************************************************************************\
*
* BamlReader.ReadPropertyComplexEndRecord
*
* Read the end of a complex property. This can be any type of complex
* property, including arrays, ILists, IDictionaries, Clr properties or
* dependency properties.
*
\***************************************************************************/
private void ReadPropertyComplexEndRecord()
{
// Pop information off the node info stack that tells us what the starting
// record was for this ending record. Check to make sure it is the
// correct type. If not, throw an exception.
BamlNodeInfo nodeInfo = (BamlNodeInfo)_nodeStack.Pop();
BamlRecordType expectedType;
switch (nodeInfo.RecordType)
{
case BamlRecordType.PropertyComplexStart:
expectedType = BamlRecordType.PropertyComplexEnd;
break;
case BamlRecordType.PropertyArrayStart:
expectedType = BamlRecordType.PropertyArrayEnd;
break;
case BamlRecordType.PropertyIListStart:
expectedType = BamlRecordType.PropertyIListEnd;
break;
case BamlRecordType.PropertyIDictionaryStart:
expectedType = BamlRecordType.PropertyIDictionaryEnd;
break;
default:
expectedType = BamlRecordType.Unknown;
break;
}
if (_currentBamlRecord.RecordType != expectedType)
{
throw new InvalidOperationException(SR.Get(SRID.BamlScopeError,
_currentBamlRecord.RecordType.ToString(),
expectedType.ToString()));
}
ClearProperties();
NodeTypeInternal = BamlNodeType.EndComplexProperty;
_name = nodeInfo.Name;
_localName = nodeInfo.LocalName;
int index = nodeInfo.Name.LastIndexOf(".", StringComparison.Ordinal);
if (index > 0)
{
_ownerTypeName = nodeInfo.Name.Substring(0, index);
}
else
{
// Eg. xmlns property
_ownerTypeName = string.Empty;
}
_assemblyName = nodeInfo.AssemblyName;
_prefix = nodeInfo.Prefix;
_xmlNamespace = nodeInfo.XmlNamespace;
_clrNamespace = nodeInfo.ClrNamespace;
_parserContext.PopScope();
_prefixDictionary.PopScope();
ReadProperties();
}
/***************************************************************************\
*
* BamlReader.ReadTextRecord
*
* Read record containing text content that goes between the start and end
* tags of an object.
*
\***************************************************************************/
private void ReadTextRecord()
{
ClearProperties();
BamlTextWithIdRecord textWithIdRecord = _currentBamlRecord as BamlTextWithIdRecord;
if (textWithIdRecord != null)
{
// Get the value string from the string table, and cache it in the
// record.
textWithIdRecord.Value = MapTable.GetStringFromStringId(
textWithIdRecord.ValueId);
}
BamlTextWithConverterRecord textWithConverter = _currentBamlRecord as BamlTextWithConverterRecord;
if (textWithConverter != null)
{
short converterTypeId = textWithConverter.ConverterTypeId;
Type converter = MapTable.GetTypeFromId(converterTypeId);
_typeConverterAssemblyName = converter.Assembly.FullName;
_typeConverterName = converter.FullName;
}
NodeTypeInternal = BamlNodeType.Text;
_prefix = string.Empty;
_value = ((BamlTextRecord)_currentBamlRecord).Value;
}
/***************************************************************************\
*
* BamlReader.ReadConstructorStart
*
* Read a start tag, which indicates that
* the following objects are to be used as constructor parameters.
*
\***************************************************************************/
private void ReadConstructorStart()
{
ClearProperties();
NodeTypeInternal = BamlNodeType.StartConstructor;
// Push information on the node stack to indicate we have a start array
BamlNodeInfo nodeInfo = new BamlNodeInfo();
nodeInfo.RecordType = BamlRecordType.ConstructorParametersStart;
_nodeStack.Push(nodeInfo);
}
/***************************************************************************\
*
* BamlReader.ReadConstructorEnd
*
* Read a <\x:ConstructorParameters ... > end tag, which indicates that
* the previous objects are to be used as constructor parameters.
*
\***************************************************************************/
private void ReadConstructorEnd()
{
ClearProperties();
NodeTypeInternal = BamlNodeType.EndConstructor;
// Pop information off the node stack that tells us what element this
// is the end of. Check to make sure the record on the stack is for a
// start element.
BamlNodeInfo nodeInfo = (BamlNodeInfo)_nodeStack.Pop();
if (nodeInfo.RecordType != BamlRecordType.ConstructorParametersStart)
{
throw new InvalidOperationException(SR.Get(SRID.BamlScopeError,
_currentBamlRecord.RecordType.ToString(),
BamlRecordType.ConstructorParametersEnd.ToString()));
}
// read properties, if any, after this end tag.
ReadProperties();
}
/****************************************************************************\
*
* BamlReader.InsertDeferedKey
*
* Search the _deferedKeys list for a dictionary key that has the same offset
* as the current baml stream position. If one is found, generate a
* def attribute record to simulate a dictionary key.
*
\***************************************************************************/
private void InsertDeferedKey(Int32 valueOffset)
{
if (_deferKeys == null)
{
return;
}
BamlKeyInfo keyInfo = _deferKeys[0];
while (keyInfo.Offset == valueOffset)
{
// Remember the _currentKeyInfo so that we can use it to resolve StaticResourceId
// records that may occur within the corresponding value.
_currentKeyInfo = keyInfo;
BamlPropertyInfo info = new BamlPropertyInfo();
info.Value = keyInfo.Value;
info.AssemblyName = string.Empty;
info.Prefix = (string)_prefixDictionary[XamlReaderHelper.DefinitionNamespaceURI];
info.XmlNamespace = XamlReaderHelper.DefinitionNamespaceURI;
info.ClrNamespace = string.Empty;
info.Name = keyInfo.Name;
info.LocalName = info.Name;
info.RecordType = BamlRecordType.DefAttribute;
AddToPropertyInfoCollection(info);
// We no longer need this key record, so remove it to make subsequent
// searches faster.
_deferKeys.RemoveAt(0);
if (_deferKeys.Count > 0)
{
keyInfo = _deferKeys[0];
}
else
{
return;
}
}
}
/***************************************************************************\
*
* BamlReader.ClearProperties
*
* Clear properties that are likely to change as different baml records
* are read in.
*
\***************************************************************************/
private void ClearProperties()
{
_value = string.Empty;
_prefix = string.Empty;
_name = string.Empty;
_localName = string.Empty;
_ownerTypeName = string.Empty;
_assemblyName = string.Empty;
_xmlNamespace = string.Empty;
_clrNamespace = string.Empty;
_connectionId = 0;
_contentPropertyName = string.Empty;
_attributeUsage = BamlAttributeUsage.Default;
_typeConverterAssemblyName = string.Empty;
_typeConverterName = string.Empty;
_properties.Clear();
}
/****************************************************************************\
*
* BamlReader.SetCommonPropertyInfo
*
* Get information that is common to all types of property records and
* fill in the passed node info record with this information.
* Return the attribute info found.
*
\***************************************************************************/
private BamlAttributeInfoRecord SetCommonPropertyInfo(
BamlNodeInfo nodeInfo,
short attrId)
{
BamlAttributeInfoRecord attrInfo = MapTable.GetAttributeInfoFromId(attrId);
BamlTypeInfoRecord typeInfo = MapTable.GetTypeInfoFromId(attrInfo.OwnerTypeId);
// Fill node info record with this data.
nodeInfo.LocalName = attrInfo.Name;
nodeInfo.Name = typeInfo.TypeFullName + "." + nodeInfo.LocalName;
string assembly, prefix, namespaceUri;
GetAssemblyAndPrefixAndXmlns(typeInfo, out assembly, out prefix, out namespaceUri);
nodeInfo.AssemblyName = assembly;
nodeInfo.Prefix = prefix;
nodeInfo.XmlNamespace = namespaceUri;
nodeInfo.ClrNamespace = typeInfo.ClrNamespace;
nodeInfo.AttributeUsage = attrInfo.AttributeUsage;
return attrInfo;
}
private string GetTemplateBindingExtensionValueString(short memberId)
{
string valueString = string.Empty;
string valuePrefix = null;
string typeName = null;
string propName = null;
if (memberId < 0)
{
memberId = (short)-memberId;
DependencyProperty dp = null;
if (memberId < (short)KnownProperties.MaxDependencyProperty)
{
KnownProperties knownId = (KnownProperties)(memberId);
{
dp = KnownTypes.GetKnownDependencyPropertyFromId(knownId);
}
}
if (dp == null)
{
throw new InvalidOperationException(SR.Get(SRID.BamlBadExtensionValue));
}
else
{
typeName = dp.OwnerType.Name;
propName = dp.Name;
}
object prefixObject = _prefixDictionary[XamlReaderHelper.DefaultNamespaceURI];
valuePrefix = (prefixObject == null) ? string.Empty : (string)prefixObject;
}
else
{
BamlAttributeInfoRecord attrInfo = MapTable.GetAttributeInfoFromId(memberId);
BamlTypeInfoRecord valueTypeInfo = MapTable.GetTypeInfoFromId(attrInfo.OwnerTypeId);
string valueXmlNamespace;
string valueAssemblyName;
GetAssemblyAndPrefixAndXmlns(valueTypeInfo, out valueAssemblyName, out valuePrefix, out valueXmlNamespace);
typeName = valueTypeInfo.TypeFullName;
typeName = typeName.Substring(typeName.LastIndexOf(".", StringComparison.Ordinal) + 1);
propName = attrInfo.Name;
}
if (valuePrefix == string.Empty)
{
valueString += typeName;
}
else
{
valueString += valuePrefix + ":" + typeName;
}
valueString += "." + propName + "}";
return valueString;
}
private string GetStaticExtensionValueString(short memberId)
{
string valueString = string.Empty;
string valuePrefix = null;
string typeName = null;
string propName = null;
string extensionPrefix = (string)_prefixDictionary[XamlReaderHelper.DefinitionNamespaceURI];
if (extensionPrefix != string.Empty)
{
valueString = "{" + extensionPrefix + ":Static ";
}
else
{
valueString = "{Static ";
}
if (memberId < 0)
{
memberId = (short)-memberId;
bool isKey = true;
// this is a known StaticExtension param.
// if keyId is more than the range it is the actual resource,
// else it is the key.
if (memberId > (short)SystemResourceKeyID.InternalSystemThemeStylesEnd)
{
memberId -= (short)SystemResourceKeyID.InternalSystemThemeStylesEnd;
isKey = false;
}
if (Enum.IsDefined(typeof(SystemResourceKeyID), (int)memberId))
{
SystemResourceKeyID keyId = (SystemResourceKeyID)memberId;
typeName = SystemKeyConverter.GetSystemClassName(keyId);
if (isKey)
{
propName = SystemKeyConverter.GetSystemKeyName(keyId);
}
else
{
propName = SystemKeyConverter.GetSystemPropertyName(keyId);
}
}
else
{
throw new InvalidOperationException(SR.Get(SRID.BamlBadExtensionValue));
}
object prefixObject = _prefixDictionary[XamlReaderHelper.DefaultNamespaceURI];
valuePrefix = (prefixObject == null) ? string.Empty : (string)prefixObject;
}
else
{
BamlAttributeInfoRecord attrInfo = MapTable.GetAttributeInfoFromId(memberId);
BamlTypeInfoRecord valueTypeInfo = MapTable.GetTypeInfoFromId(attrInfo.OwnerTypeId);
string valueXmlNamespace;
string valueAssemblyName;
GetAssemblyAndPrefixAndXmlns(valueTypeInfo, out valueAssemblyName, out valuePrefix, out valueXmlNamespace);
typeName = valueTypeInfo.TypeFullName;
typeName = typeName.Substring(typeName.LastIndexOf(".", StringComparison.Ordinal) + 1);
propName = attrInfo.Name;
}
if (valuePrefix == string.Empty)
{
valueString += typeName;
}
else
{
valueString += valuePrefix + ":" + typeName;
}
valueString += "." + propName + "}";
return valueString;
}
private string GetExtensionPrefixString(string extensionName)
{
string valueString = string.Empty;
string extensionPrefix = (string)_prefixDictionary[XamlReaderHelper.DefaultNamespaceURI];
if (!string.IsNullOrEmpty(extensionPrefix))
{
valueString = "{" + extensionPrefix + ":" + extensionName + " ";
}
else
{
valueString = "{" + extensionName + " ";
}
return valueString;
}
private string GetInnerExtensionValueString(IOptimizedMarkupExtension optimizedMarkupExtensionRecord)
{
string valueString = string.Empty;
short memberId = optimizedMarkupExtensionRecord.ValueId;
if (optimizedMarkupExtensionRecord.IsValueTypeExtension)
{
valueString = GetTypeValueString(memberId);
}
else if (optimizedMarkupExtensionRecord.IsValueStaticExtension)
{
valueString = GetStaticExtensionValueString(memberId);
}
else
{
valueString = MapTable.GetStringFromStringId(memberId);
}
return valueString + "}";
}
private string GetExtensionValueString(IOptimizedMarkupExtension optimizedMarkupExtensionRecord)
{
string valueString = string.Empty;
short memberId = optimizedMarkupExtensionRecord.ValueId;
short extensionId = optimizedMarkupExtensionRecord.ExtensionTypeId;
switch (extensionId)
{
case (short)KnownElements.StaticExtension:
valueString = GetStaticExtensionValueString(memberId);
break;
case (short)KnownElements.TemplateBindingExtension:
valueString = GetExtensionPrefixString("TemplateBinding");
valueString += GetTemplateBindingExtensionValueString(memberId);
break;
case (short)KnownElements.DynamicResourceExtension:
valueString = GetExtensionPrefixString("DynamicResource");
valueString += GetInnerExtensionValueString(optimizedMarkupExtensionRecord);
break;
case (short)KnownElements.StaticResourceExtension:
valueString = GetExtensionPrefixString("StaticResource");
valueString += GetInnerExtensionValueString(optimizedMarkupExtensionRecord);
break;
}
return valueString;
}
/****************************************************************************\
*
* BamlReader.GetTypeValueString
*
* Construct a MarkupExtension that represents the type given its ID in the
* BamlMapTable.
*
\***************************************************************************/
private string GetTypeValueString(short typeId)
{
string typeExtensionPrefix = (string)_prefixDictionary[XamlReaderHelper.DefinitionNamespaceURI];
string valueString;
if (typeExtensionPrefix != string.Empty)
{
valueString = "{" + typeExtensionPrefix + ":Type ";
}
else
{
valueString = "{Type ";
}
BamlTypeInfoRecord valueTypeInfo = MapTable.GetTypeInfoFromId(typeId);
string valueXmlNamespace;
string valuePrefix;
string valueAssemblyName;
GetAssemblyAndPrefixAndXmlns(valueTypeInfo, out valueAssemblyName, out valuePrefix, out valueXmlNamespace);
string typeName = valueTypeInfo.TypeFullName;
typeName = typeName.Substring(typeName.LastIndexOf(".", StringComparison.Ordinal) + 1);
if (valuePrefix == string.Empty)
{
valueString += typeName;
}
else
{
valueString += valuePrefix + ":" + typeName;
}
valueString +="}";
return valueString;
}
/***************************************************************************\
*
* BamlReader.GetAssemblyAndPrefixAndXmlns
*
* Get a namespace prefix and the associated Xml namespace for a given type.
* If none, return empty strings.
*
\***************************************************************************/
private void GetAssemblyAndPrefixAndXmlns(
BamlTypeInfoRecord typeInfo,
out string assemblyFullName,
out string prefix,
out string xmlns)
{
// If the typeInfo indicates the type is NOT a core Avalon type, then the
// assembly should be in the Assembly table of the BamlMapTable. Otherwise
// we have to get the Assembly information from the actual type.
if (typeInfo.AssemblyId >= 0 || typeInfo.Type == null)
{
BamlAssemblyInfoRecord assyInfo = MapTable.GetAssemblyInfoFromId(
typeInfo.AssemblyId);
assemblyFullName = assyInfo.AssemblyFullName;
}
else
{
Assembly typeAssembly = typeInfo.Type.Assembly;
assemblyFullName = typeAssembly.FullName;
}
// Look through the mapping table for an xml namespace that matches
// the assembly and type namespace.
// Note that it may be one of the known namespaces, such as the definition
// namespace so check for that first.
if (typeInfo.ClrNamespace == "System.Windows.Markup" &&
(assemblyFullName.StartsWith("PresentationFramework", StringComparison.Ordinal)
|| assemblyFullName.StartsWith("System.Xaml", StringComparison.Ordinal)))
{
xmlns = XamlReaderHelper.DefinitionNamespaceURI;
}
else
{
// XamlTypeMapper only stored MappingPI Xml Namesaces
xmlns = _parserContext.XamlTypeMapper.GetXmlNamespace(
typeInfo.ClrNamespace, assemblyFullName);
// Now check our own private list for URI based Xml Namespaces
if(String.IsNullOrEmpty(xmlns))
{
List xmlnsList = GetXmlNamespaceList(typeInfo.ClrNamespace, assemblyFullName);
prefix = GetXmlnsPrefix(xmlnsList);
return;
}
}
prefix = GetXmlnsPrefix(xmlns);
}
// store the all XmlNs UIRs that map to each CLRNamespace + AssemblyName
private void SetXmlNamespace(string clrNamespace, string assemblyFullName, string xmlNs)
{
String fullName = clrNamespace + "#" + assemblyFullName;
List list;
if(_reverseXmlnsTable.ContainsKey(fullName))
{
list = _reverseXmlnsTable[fullName];
}
else
{
list = new List();
_reverseXmlnsTable[fullName] = list;
}
list.Add(xmlNs);
}
// Retrieve the XmlNs UIRs that map to a CLRNamespace + AssemblyName
private List GetXmlNamespaceList(string clrNamespace, string assemblyFullName)
{
String fullName = clrNamespace + "#" + assemblyFullName;
List xmlnsList=null;
if (_reverseXmlnsTable.ContainsKey(fullName))
{
xmlnsList = _reverseXmlnsTable[fullName];
}
return xmlnsList;
}
internal string GetXmlnsPrefix(string xmlns)
{
string prefix = string.Empty;
// If we don't find an xmlns, then the clr namespace must be in the
// default definition file group for this file. Otherwise, lookup the
// prefix in the xmlns-to-prefix dictionary built up in ReadXmlnsProperty
if (xmlns == string.Empty)
{
xmlns = _parserContext.XmlnsDictionary[string.Empty];
}
else
{
object prefixObject = _prefixDictionary[xmlns];
// If there is nothing in the prefix dictionary for this namespace,
// then assume this is the default namespace and set prefix to
// an empty string.
if (prefixObject != null)
{
prefix = (string)prefixObject;
}
}
return prefix;
}
private string GetXmlnsPrefix(List xmlnsList)
{
string prefix;
string xmlns;
if (xmlnsList != null)
{
// return the first non-null prefix defined.
// the default prefix is "" and is non-null.
for (int i=0; i _deferKeys;
// Info for the key being currently read.
private BamlKeyInfo _currentKeyInfo;
// The currently active StaticResourceInfo
private List _currentStaticResourceRecords;
private int _currentStaticResourceRecordIndex;
// The type of current BAML node (or a condensed version of the real baml record type)
private BamlNodeType _bamlNodeType;
// The current read state of this BamlReader.
private ReadState _readState;
// The value of the assembly name for the current node
private string _assemblyName;
// The value of the namespace prefix for the current node
private string _prefix;
// Xml namespace for the current node;
private string _xmlNamespace;
// Clr namespace for the current node;
private string _clrNamespace;
// The attribute value for the current node, if a property or namespace
private string _value;
// The fully qualified name of the current node
private string _name;
// The local part of the name of the current node, without class or prefix
private string _localName;
// The fully qualified class name of the current node's owner type, without prefix
// Applies only to properties and events
private string _ownerTypeName;
// Arraylist of various PropertyInfo objects in the order retrieved from the baml stream
private ArrayList _properties;
// DP value of a property. If this is set the type of this property is used to resolve the
// value of any subsequent property. Setter.Property & Setter.Value is an example of this sceanrio.
private DependencyProperty _propertyDP;
// Index of current property in _properties collection that is being viewed.
private int _propertiesIndex;
// connection Id of current element for hooking up IDs and events.
private Int32 _connectionId;
// contentProperty Name of current element.
private string _contentPropertyName;
// Defines what this property is used for such as being an alias for
// xml:lang, xml:space or x:ID
private BamlAttributeUsage _attributeUsage;
// Stack of node information about the element tree being built.
private Stack _nodeStack;
// Context information used when reading baml file. This contains the XamlTypeMapper used
// for resolving binary property information into strings.
private ParserContext _parserContext;
private bool _isInjected;
private bool _useTypeConverter;
private string _typeConverterAssemblyName;
private string _typeConverterName;
// Maps CLRNameSpace#AssemblyFullName <--> List of XmlNamespacesURIs.
private Dictionary> _reverseXmlnsTable;
#endregion Data
/***************************************************************************\
*
* BamlNodeInfo
*
* This class holds information about a single element or other node record
* that is encountered when reading the baml file.
*
\***************************************************************************/
//
// This code should always be transparent. Meaning you should never add
// SecurityCritical to this section of the code.
//
internal class BamlNodeInfo
{
// Create an empty property info record
internal BamlNodeInfo()
{
}
// The type of record, be it element, complex property, array, etc.
internal BamlRecordType RecordType
{
get { return _recordType; }
set { _recordType = value; }
}
// The value of the assembly name for the declaring type of the current node or property
internal string AssemblyName
{
get { return _assemblyName; }
set { _assemblyName = value; }
}
// The value of the namespace prefix for the current node or property
internal string Prefix
{
get { return _prefix; }
set { _prefix = value; }
}
// Xml namespace for the current node or property
internal string XmlNamespace
{
get { return _xmlNamespace; }
set { _xmlNamespace = value; }
}
// Clr namespace for the current node or property
internal string ClrNamespace
{
get { return _clrNamespace; }
set { _clrNamespace = value; }
}
// The fully qualified name of the current node or property
internal string Name
{
get { return _name; }
set { _name = value; }
}
// The local part of the name of the current node or property
internal string LocalName
{
get { return _localName; }
set { _localName = value; }
}
// Defines what this property is used for such as being an alias for
// xml:lang, xml:space or x:ID
internal BamlAttributeUsage AttributeUsage
{
get { return _attributeUsage; }
set { _attributeUsage = value; }
}
// The type of record, be it element, complex property, array, etc.
private BamlRecordType _recordType;
// The value of the assembly name for the declaring type of the current node or property
private string _assemblyName;
// The value of the namespace prefix for the current node or property
private string _prefix;
// Xml namespace for the current node or property
private string _xmlNamespace;
// Clr namespace for the current node or property
private string _clrNamespace;
// The fully qualified name of the current node or property
private string _name;
// The local part of the name of the current node or property
private string _localName;
// Defines what this property is used for such as being an alias for
// xml:lang, xml:space or x:ID
private BamlAttributeUsage _attributeUsage;
}
/***************************************************************************\
*
* BamlPropertyInfo
*
* This class holds information about a single Baml property record that is
* encountered when reading all the property-like records on an element.
*
\***************************************************************************/
//
// This code should always be transparent. Meaning you should never add
// SecurityCritical to this section of the code.
//
internal class BamlPropertyInfo : BamlNodeInfo
{
// Create an empty property info record
internal BamlPropertyInfo()
{
}
// The string value for the current property
internal string Value
{
get { return _value; }
set { _value = value; }
}
// The string value for the current property
private string _value;
}
/***************************************************************************\
*
* BamlContentPropertyInfo
*
* This class holds information about a single Baml property record that is
* encountered when reading all the property-like records on an element.
*
\***************************************************************************/
//
// This code should always be transparent. Meaning you should never add
// SecurityCritical to this section of the code.
//
internal class BamlContentPropertyInfo : BamlNodeInfo
{
// this doesn't need any different fields it just needs to be
// a different type.
}
/****************************************************************************\
*
* BamlKeyInfo
*
* This class holds information about a single Baml property record that is
* encountered when reading all the property-like records on an element.
*
\***************************************************************************/
//
// This code should always be transparent. Meaning you should never add
// SecurityCritical to this section of the code.
//
[DebuggerDisplay("{_offset}")]
internal class BamlKeyInfo : BamlPropertyInfo
{
// Create an empty info record
internal BamlKeyInfo()
{
}
// The offset of the value from the start of the values section.
internal Int32 Offset
{
get { return _offset; }
set { _offset = value; }
}
internal List> StaticResources
{
get
{
if (_staticResources == null)
{
_staticResources = new List>();
}
return _staticResources;
}
}
private Int32 _offset;
private List> _staticResources;
}
}
}
// 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
- DiscoveryClientDuplexChannel.cs
- Listbox.cs
- OracleCommandSet.cs
- KeyPressEvent.cs
- ExitEventArgs.cs
- XmlQueryRuntime.cs
- SqlDelegatedTransaction.cs
- LambdaCompiler.cs
- AsyncResult.cs
- DbBuffer.cs
- ListViewGroupConverter.cs
- ResourceContainer.cs
- VisualStyleTypesAndProperties.cs
- DynamicPropertyHolder.cs
- DetailsViewDeleteEventArgs.cs
- XmlSchemaProviderAttribute.cs
- HtmlValidationSummaryAdapter.cs
- WaitForChangedResult.cs
- SecurityMessageProperty.cs
- StylusPointPropertyInfoDefaults.cs
- BlockUIContainer.cs
- TextModifier.cs
- WebContext.cs
- ListBindingHelper.cs
- BodyGlyph.cs
- Polygon.cs
- RenderData.cs
- HttpApplication.cs
- SubpageParaClient.cs
- QueryInterceptorAttribute.cs
- SharedStream.cs
- LinqDataSource.cs
- XmlBinaryReader.cs
- StorageEndPropertyMapping.cs
- SiteMapNode.cs
- PageStatePersister.cs
- SchemaRegistration.cs
- WizardDesigner.cs
- VisualBasicExpressionConverter.cs
- MetafileHeaderWmf.cs
- DrawingBrush.cs
- XmlCharType.cs
- CancellationTokenRegistration.cs
- DataListCommandEventArgs.cs
- GifBitmapEncoder.cs
- MissingMemberException.cs
- PageContent.cs
- ToolStripPanelSelectionGlyph.cs
- CacheDependency.cs
- ProcessHost.cs
- CustomDictionarySources.cs
- TextStore.cs
- BookmarkOptionsHelper.cs
- RolePrincipal.cs
- webclient.cs
- SqlUtils.cs
- DataGridViewRowPostPaintEventArgs.cs
- OracleConnection.cs
- DbDataReader.cs
- ToolStripItemTextRenderEventArgs.cs
- ConfigurationStrings.cs
- BinaryCommonClasses.cs
- DataTableTypeConverter.cs
- ThicknessKeyFrameCollection.cs
- EndpointDiscoveryMetadata.cs
- TypeNameConverter.cs
- PageCanvasSize.cs
- GenericTypeParameterConverter.cs
- WpfKnownMemberInvoker.cs
- UriTemplateMatchException.cs
- RIPEMD160Managed.cs
- DocumentApplicationState.cs
- TextCharacters.cs
- EventLogStatus.cs
- Version.cs
- FixedPageProcessor.cs
- _NetRes.cs
- ChangePassword.cs
- DefaultPropertyAttribute.cs
- Geometry3D.cs
- ShutDownListener.cs
- AutoResetEvent.cs
- SplashScreen.cs
- GridViewCancelEditEventArgs.cs
- LinearGradientBrush.cs
- Atom10FeedFormatter.cs
- XmlSchemaComplexContent.cs
- SafeRightsManagementPubHandle.cs
- CollectionViewProxy.cs
- BasicHttpSecurity.cs
- PermissionSetEnumerator.cs
- KnownBoxes.cs
- MemberMemberBinding.cs
- TextParagraphProperties.cs
- SecureStringHasher.cs
- PolyQuadraticBezierSegment.cs
- AssemblyAssociatedContentFileAttribute.cs
- ProfileServiceManager.cs
- DatasetMethodGenerator.cs
- LogLogRecord.cs