XamlTypeMapper.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Markup / XamlTypeMapper.cs / 1600166 / XamlTypeMapper.cs

                             
//----------------------------------------------------------------------------
//
// File: XamlTypeMapper.cs
// 
// Description:
//  Maps namespaceURI and LocalName to appropriate element, properties, and events. 
// 
//
// History: 
//    7/19/01:    rogerg        Created
//    5/28/03:    peterost      Ported to wcp
//    9/20/04:    peterost      cleanup interfaces and caches
// 
// Copyright (C) 2003 by Microsoft Corporation.  All rights reserved.
// 
//--------------------------------------------------------------------------- 

using System; 
using System.Xml;
using System.IO;
using System.Text;
using System.Collections; 
using System.Collections.Generic;
using System.Globalization; 
using System.ComponentModel; 
using System.Collections.Specialized;
using System.Diagnostics; 
using System.Reflection;
using MS.Utility;

#if !PBTCOMPILER 

using System.Windows; 
using System.Windows.Markup; 
using System.Windows.Resources;
using System.Windows.Threading; 
using SecurityHelper=MS.Internal.PresentationFramework.SecurityHelper;
using MS.Internal;  // CriticalExceptions

#else 

using System.Runtime.CompilerServices; 
 
#endif
 
// Disabling 1634 and 1691:
// In order to avoid generating warnings about unknown message numbers and
// unknown pragmas when compiling C# source code with the C# compiler,
// you need to disable warnings 1634 and 1691. (Presharp Documentation) 
#pragma warning disable 1634, 1691
 
#if PBTCOMPILER 
namespace MS.Internal.Markup
#else 
namespace System.Windows.Markup
#endif
{
 
    ///
    /// Handles mapping between XML NamepaceURI and .NET namespace types 
    /// 
#if PBTCOMPILER
    internal class XamlTypeMapper 
#else
    public partial class XamlTypeMapper
#endif
    { 
#region Public
 
#region Methods 

#if !PBTCOMPILER 
        /// 
        /// Constructor
        /// 
        /// Assemblies XamlTypeMapper should use when resolving XAML 
        public XamlTypeMapper(string[] assemblyNames)
        { 
            if(null == assemblyNames) 
            {
                throw new ArgumentNullException( "assemblyNames" ); 
            }

            _assemblyNames = assemblyNames;
            _namespaceMaps = null; 
        }
#endif 
 
        /// 
        /// Constructor 
        /// 
        /// Assemblies XamlTypeMapper should use when resolving XAML
        /// NamespaceMap the XamlTypeMapper should use when resolving XAML
        public XamlTypeMapper( 
            string[] assemblyNames,
            NamespaceMapEntry[] namespaceMaps) 
        { 
            if(null == assemblyNames)
            { 
                throw new ArgumentNullException( "assemblyNames" );
            }

            _assemblyNames = assemblyNames; 
            _namespaceMaps = namespaceMaps;
#if PBTCOMPILER 
            _hasInternals = false; 
            _hasLocalReference = false;
#endif 
        }

        /// 
        /// Helper to map an Xaml tag to a DotNet Type 
        /// 
        ///  
        /// Example: 
        ///     If the xml contained the tags 
        ///     you would call XamlTypeMapper.GetType("AvalonBase","Button"); 
        ///     
        ///     Note the XmlNamespace "AvalonBase" is the actual namespace value, not
        ///     the base: prefix.
        ///  
        /// NamespaceURI of tag
        /// localName of the Tag 
        /// Type for the object. If no type was found NULL is returned 
        public Type GetType(
            string xmlNamespace, 
            string localName)
        {
            if(null == xmlNamespace)
            { 
                throw new ArgumentNullException( "xmlNamespace" );
            } 
            if(null == localName) 
            {
                throw new ArgumentNullException( "localName" ); 
            }

            TypeAndSerializer typeAndSerializer =
                GetTypeOnly(xmlNamespace,localName); 

            return typeAndSerializer != null ? typeAndSerializer.ObjectType : null; 
        } 

#if !PBTCOMPILER 
        /// 
        ///  Programmatic counterpart to the  XAML PI.  For example, 
        ///    
        ///  
        /// 
        /// The "swc" argument in the mapping PI example. 
        ///  
        /// 
        /// The "System.Windows.ComponentModel" argument in the mapping PI example. 
        /// 
        /// 
        /// The "PresentationFramework" argument in the mapping PI example.
        ///  
        public void AddMappingProcessingInstruction(
            string  xmlNamespace, 
            string  clrNamespace, 
            string  assemblyName )
        { 
            if( null == xmlNamespace )
            {
                throw new ArgumentNullException("xmlNamespace");
            } 
            if( null == clrNamespace )
            { 
                throw new ArgumentNullException("clrNamespace"); 
            }
            if( null == assemblyName ) 
            {
                throw new ArgumentNullException("assemblyName");
            }
 
            // Parameter validation : Check for String.Empty as well?
 
            // Add mapping to the table keyed by xmlNamespace 
            ClrNamespaceAssemblyPair pair = new ClrNamespaceAssemblyPair(clrNamespace, assemblyName);
            PITable[xmlNamespace] = pair; 

            // Add mapping to the table keyed by assembly and clrnamespace
            string upperAssemblyName = assemblyName.ToUpper(
                                              TypeConverterHelper.InvariantEnglishUS); 
            String fullName = clrNamespace + "#" + upperAssemblyName;
 
            _piReverseTable[fullName] = xmlNamespace; 

            // Add mapping to the SchemaContext 
            if (_schemaContext != null)
            {
                _schemaContext.SetMappingProcessingInstruction(xmlNamespace, pair);
            } 
        }
#endif 
        ///  
        ///     This allows specifying a path to use when loading the named assembly.
        ///  
        /// 
        /// The short name of the assembly, with no extension or path specified
        /// 
        ///  
        /// The file path of the assembly
        ///  
        public void SetAssemblyPath( 
            string assemblyName,
            string assemblyPath) 
        {
            if( null == assemblyName )
            {
                throw new ArgumentNullException("assemblyName"); 
            }
            if( null == assemblyPath ) 
            { 
                throw new ArgumentNullException("assemblyPath");
            } 
            if (assemblyPath == string.Empty)
            {
                _lineNumber = 0;  // Public API, so we don't know the line number.
                ThrowException(SRID.ParserBadAssemblyPath); 
            }
            if (assemblyName == string.Empty) 
            { 
                _lineNumber = 0;  // Public API, so we don't know the line number.
                ThrowException(SRID.ParserBadAssemblyName); 
            }

            string asmName = assemblyName.ToUpper(CultureInfo.InvariantCulture);
            lock (_assemblyPathTable) 
            {
                _assemblyPathTable[asmName] = assemblyPath; 
            } 

#if PBTCOMPILER 
            PreLoadDefaultAssemblies(asmName, assemblyPath);
#else
            // Allow people to reset the path of previously loaded assemblies
            // so they can be loaded again.   The is the Dev build/load/build/load 
            // Designer scenario.  (Don't mess with GACed assemblies)
            Assembly assem = ReflectionHelper.GetAlreadyLoadedAssembly(asmName); 
            if (assem != null && !assem.GlobalAssemblyCache) 
            {
                ReflectionHelper.ResetCacheForAssembly(asmName); 
                // No way to reset SchemaContext at assembly granularity, so just reset the whole context
                if (_schemaContext != null)
                {
                    _schemaContext = null; 
                }
            } 
#endif 
        }
 
#endregion Methods

#region Properties
 
        /// 
        ///  Instance of XamlTypeMapper to use if none is specified in a 
        ///  ParserContext.  XamlTypeMapper returned is the internal default. 
        /// 
        public static XamlTypeMapper DefaultMapper 
        {
            get
            {
                return XmlParserDefaults.DefaultMapper; 
            }
        } 
 
#endregion Properties
 
#endregion Public

#region Internal
 
#region Initialization
 
#if !PBTCOMPILER 
        ///
        /// Initialize the XamlTypeMapper so that it is ready for a parse operation. 
        ///
        internal void Initialize()
        {
            _typeLookupFromXmlHashtable.Clear(); 
            _namespaceMapHashList.Clear();
            _piTable.Clear(); 
            _piReverseTable.Clear(); 
            lock (_assemblyPathTable)
            { 
                _assemblyPathTable.Clear();
            }
            _referenceAssembliesLoaded = false;
        } 
#endif
 
        // Return a new XamlTypeMapper that has the same instance variables as this instance, 
        // will all complex properties deep copied.
#if !PBTCOMPILER 
        internal XamlTypeMapper Clone()
        {
            XamlTypeMapper newMapper = new XamlTypeMapper(_assemblyNames.Clone() as string[]);
 
            newMapper._mapTable = _mapTable;
            newMapper._referenceAssembliesLoaded = _referenceAssembliesLoaded; 
            newMapper._lineNumber = _lineNumber; 
            newMapper._linePosition = _linePosition;
 
            newMapper._namespaceMaps = _namespaceMaps.Clone() as NamespaceMapEntry[];
            newMapper._typeLookupFromXmlHashtable = _typeLookupFromXmlHashtable.Clone() as Hashtable;
            newMapper._namespaceMapHashList = _namespaceMapHashList.Clone() as Hashtable;
            newMapper._typeInformationCache = CloneHybridDictionary(_typeInformationCache); 
            newMapper._piTable = CloneHybridDictionary(_piTable);
            newMapper._piReverseTable = CloneStringDictionary(_piReverseTable); 
            newMapper._assemblyPathTable = CloneHybridDictionary(_assemblyPathTable); 

            return newMapper; 
        }
#endif

#if !PBTCOMPILER 
        private HybridDictionary CloneHybridDictionary(HybridDictionary dict)
        { 
            HybridDictionary newDict = new HybridDictionary(dict.Count); 
            foreach ( DictionaryEntry de in dict )
            { 
                newDict.Add(de.Key, de.Value);
            }
            return newDict;
        } 
#endif
 
#if !PBTCOMPILER 
        private Dictionary CloneStringDictionary(Dictionary dict)
        { 
            Dictionary newDict = new Dictionary();
            foreach (KeyValuePair kvp in dict)
            {
                newDict.Add(kvp.Key, kvp.Value); 
            }
            return newDict; 
        } 
#endif
 
#endregion Initialization

#region Assemblies
 
        ///
        /// Returns the assembly path for the passed assembly.  If none, return null. 
        /// 
        internal string AssemblyPathFor(string assemblyName)
        { 
            string path = null;
            if (assemblyName != null)
            {
                // This method is used by SchemaContext, which needs to be thread-safe, so lock around it 
                lock (_assemblyPathTable)
                { 
                    path = _assemblyPathTable[assemblyName.ToUpper( 
                                            CultureInfo.InvariantCulture)] as string;
                } 
            }

#if PBTCOMPILER
 
            if (path == null)
            { 
                // If the assembly name contains full assembly name, we should use the short 
                // assembly name to search the assembly path cache table.
 
                int indexComma = assemblyName.IndexOf(",", StringComparison.Ordinal);

                if (indexComma > 0)
                { 
                    string assemblyShortName = assemblyName.Substring(0, indexComma).ToUpper(CultureInfo.InvariantCulture);
                    path = _assemblyPathTable[assemblyShortName] as String; 
                } 
            }
#endif 

            return path;
        }
 
        /// 
        /// Load assemblies that are in the referenced assembly list passed to the XamlTypeMapper 
        /// by the compiler.  Don't load known assemblies that should already be present, 
        /// since the references may not be the correct versions (see windows bugs 927372
        /// and 929395) 
        /// 
        private bool LoadReferenceAssemblies()
        {
            if (!_referenceAssembliesLoaded) 
            {
                _referenceAssembliesLoaded = true; 
                foreach (DictionaryEntry entry in _assemblyPathTable) 
                {
                    ReflectionHelper.LoadAssembly(entry.Key as String, entry.Value as String); 
                }
                return true;
            }
            else 
            {
                // Already loaded, so they don't need to be loaded again 
                return false; 
            }
        } 

#endregion Assemblies

#region AssemblyLoading 

#if  PBTCOMPILER 
 
        private void PreLoadDefaultAssemblies(string asmName, string asmPath)
        { 
            if (AssemblyWB == null && string.Compare(asmName, _assemblyNames[0], StringComparison.OrdinalIgnoreCase) == 0)
            {
                AssemblyWB = ReflectionHelper.LoadAssembly(asmName, asmPath);
            } 
            else if (AssemblyPC == null && string.Compare(asmName, _assemblyNames[1], StringComparison.OrdinalIgnoreCase) == 0)
            { 
                AssemblyPC = ReflectionHelper.LoadAssembly(asmName, asmPath); 
            }
            else if (AssemblyPF == null && string.Compare(asmName, _assemblyNames[2], StringComparison.OrdinalIgnoreCase) == 0) 
            {
                AssemblyPF = ReflectionHelper.LoadAssembly(asmName, asmPath);
            }
            else if (string.Compare(asmName, "SYSTEM.XML", StringComparison.OrdinalIgnoreCase) == 0) 
            {
                // make sure System.Xml is at least loaded as ReflectionOnly 
                ReflectionHelper.LoadAssembly(asmName, asmPath); 
            }
            else if (string.Compare(asmName, "SYSTEM", StringComparison.OrdinalIgnoreCase) == 0) 
            {
                // make sure System is at least loaded as ReflectionOnly
                ReflectionHelper.LoadAssembly(asmName, asmPath);
            } 
        }
 
        private ResolveEventHandler _areh = null; 

        internal void SetReflectionOnlyAssemblyResolver() 
        {
            // Register handler for prerequisite assemblies.  We may not necessarily load them
            // in the correct order, so the handler is responsbile for loading required assemblies.
            if (_areh == null) 
            {
                _areh = new ResolveEventHandler(OnReferencedAssemblyResolve); 
                AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += _areh; 
            }
        } 

        internal void ClearReflectionOnlyAssemblyResolver()
        {
            if (_areh != null) 
            {
                AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve -= _areh; 
                _areh = null; 
            }
        } 

        // This event handler is called when a ReflectionOnlyLoad can't succeed because of
        // a required assembly not being present.  This handler attempts to load that
        // assembly from the known place where the root assembly lives. 
        // NOTE:  It is assumed that all prerequisite assemblies are in the assembly path
        //        table passed to the TypeMapper via SetAssemblyPath(). 
        private Assembly OnReferencedAssemblyResolve( 
            object sender,
            ResolveEventArgs args) 
        {
            if (_assemblyPathTable != null && _assemblyPathTable.Count > 0)
            {
                AssemblyName assemblyName = new AssemblyName(args.Name); 
                string assemblyShortName = assemblyName.Name;
                assemblyShortName = assemblyShortName.ToUpper(CultureInfo.InvariantCulture); 
 
                Assembly asm = ReflectionHelper.GetAlreadyReflectionOnlyLoadedAssembly(assemblyShortName);
                if (asm != null) 
                {
                    if (assemblyName.Version != null)
                    {
                        AssemblyName cachedName = new AssemblyName(asm.FullName); 
                        if (!AssemblyName.ReferenceMatchesDefinition(assemblyName, cachedName))
                        { 
                            string request = assemblyName.ToString(); 
                            string found = cachedName.ToString();
                            throw new InvalidOperationException(SR.Get(SRID.ParserAssemblyLoadVersionMismatch, request, found)); 
                        }
                    }
                    return asm;
                } 
                else
                { 
                    string assemblyFullPath = _assemblyPathTable[args.Name] as String; 

                    if (!String.IsNullOrEmpty(assemblyFullPath) && File.Exists(assemblyFullPath)) 
                    {
                       return ReflectionHelper.LoadAssembly(args.Name, assemblyFullPath);
                    }
                } 
            }
 
            return ReflectionHelper.LoadAssembly(args.Name, null); 
        }
#endif 

#endregion AssemblyLoading

        #region Events 

#if !PBTCOMPILER 
 
        /// 
        /// Helper to map an Attribute to a RoutedEvent 
        /// 
        /// 
        ///    Example: 
        ///     If the xaml contained the tag  
        ///     you would call 
        /// 
        ///         Type owner = XamlTypeMapper.GetType("BaseXmlNs","Button");  
        ///         RoutedEvent = XamlTypeMapper.GetRoutedEvent(owner,"MyClick","BaseXmlNs");
        ///  
        /// Type of the owner
        /// Xml NamespaceURI of the attribute
        /// Local name of the attribute
        /// The RoutedEvent ID or null if no match was found 
        /// 
        internal RoutedEvent GetRoutedEvent( 
            Type   owner, 
            string xmlNamespace,
            string localName) 
        {
            Type baseType = null;
            string dynamicObjectName = null;
 
            if(null == localName)
            { 
                throw new ArgumentNullException( "localName" ); 
            }
            if(null == xmlNamespace) 
            {
                throw new ArgumentNullException( "xmlNamespace" );
            }
            if (owner != null && !ReflectionHelper.IsPublicType(owner)) 
            {
                _lineNumber = 0;  // Public API, so we don't know the line number. 
                ThrowException(SRID.ParserOwnerEventMustBePublic, owner.FullName ); 
            }
 
            RoutedEvent Event = GetDependencyObject(true,owner,xmlNamespace,
                localName,ref baseType,ref dynamicObjectName)
                as RoutedEvent;
 
            return Event;
 
        } 

#endif 

#endregion Events

#region Properties 

#if !PBTCOMPILER 
        /// 
        /// Converts the string representation of an Attribute Value to an appropriate
        /// Type for the Property.  This handles use of type converters and the special 
        /// *prefix:Type.Field syntax for enums, static properties and fields.
        /// 
        ///Target object that the property needs to be set on
        ///Type of the property 
        ///Name of the property.  This is used only for
        ///                       error reporting and some pre-validation 
        ///DependencyProperty or PropertyInfo or FieldInfo. This is used 
        ///         for evaluating the TypeConverter to be used for conversion
        ///Context for the type converter 
        ///Context for enum, field and property resolution
        ///string value of the property the Attribute
        ///typeId of converter to use for paring the attribute value
        /// 
        /// An Object for the attribute value is returned.
        /// Null is returned if no TypeConverter for the Property type. 
        /// 
        //[CodeAnalysis("AptcaMethodsShouldOnlyCallAptcaMethods")] //Tracking Bug: 29647
        internal Object ParseProperty( 
            object                 targetObject,
            Type                   propType,
            string                 propName,
            object                 dpOrPiOrFi, 
            ITypeDescriptorContext typeContext,
            ParserContext          parserContext, 
            string                 value, 
            short                  converterTypeId)
        { 
            _lineNumber = parserContext != null ? parserContext.LineNumber : 0;
            _linePosition = parserContext != null ? parserContext.LinePosition : 0;

            // If value is to be converted to a string, just return the string itself instead of 
            // going needlessly through the TC. But check that the target prop Type can accept strings.
            if (converterTypeId < 0 && ((short)-converterTypeId == (short)KnownElements.StringConverter)) 
            { 
                if (propType == typeof(object) || propType == typeof(string))
                { 
                    return value;
                }
                else
                { 
                    string message = SR.Get(SRID.ParserCannotConvertPropertyValueString, value, propName, propType.FullName);
                    XamlParseException.ThrowException(parserContext, _lineNumber, _linePosition, message, null); 
                } 
            }
 
            Object obj = null;   // Object to return
            TypeConverter typeConvert;

            if (converterTypeId != 0) 
            {
                typeConvert = parserContext.MapTable.GetConverterFromId(converterTypeId, propType, parserContext); 
            } 
            else
            { 
                // NOTE: This may still be a known converter. This is typically the case when adding
                // a text Record. This should also be potentially optimized by resolving & writing out the
                // TC at compile time.
 
                // Reflect for per property type converter or type converter based on the property's type
                typeConvert = GetPropertyConverter(propType, dpOrPiOrFi); 
 
                #if DEBUG
                if( propType.Assembly.FullName == "PresentationFramework" 
                    ||
                    propType.Assembly.FullName == "PresentationCore"
                    ||
                    propType.Assembly.FullName == "WindowsBase" ) 
                {
                    Debug.WriteLine( "Reflected for type converter on " + propType.Name + "." + propName ); 
                } 
                #endif
            } 

#if !STRESS
            try
            { 
#endif
                obj =  typeConvert.ConvertFromString(typeContext, TypeConverterHelper.InvariantEnglishUS, value); 
 
                if( TraceMarkup.IsEnabled )
                { 
                    TraceMarkup.TraceActivityItem( TraceMarkup.TypeConvert,
                                                 typeConvert,
                                                 value,
                                                 obj ); 
                }
#if !STRESS 
            } 
            catch (Exception e)
            { 
                if( CriticalExceptions.IsCriticalException(e) || e is XamlParseException )
                {
                    throw;
                } 

                // If the targetObject can provide a fallback value for this property then use that instead 
 
                IProvidePropertyFallback iProvidePropertyFallback = targetObject as IProvidePropertyFallback;
                if (iProvidePropertyFallback != null && iProvidePropertyFallback.CanProvidePropertyFallback(propName)) 
                {
                    obj = iProvidePropertyFallback.ProvidePropertyFallback(propName, e);

                    if( TraceMarkup.IsEnabled ) 
                    {
                        TraceMarkup.TraceActivityItem( TraceMarkup.TypeConvertFallback, 
                                                     typeConvert, 
                                                     value,
                                                     obj ); 
                    }
                }

                // If we got the default object TypeConverter, then we know the conversion will 
                // fail, so create a more meaningful error message here.
                else if (typeConvert.GetType() == typeof(TypeConverter)) 
                { 
                    string message;
                    if( propName != string.Empty ) 
                    {
                        //  and there's no TypeConverter
                        //  to handle converting "SomeText" into an instance of something
                        //  that can be set into SomeProp. 
                        message = SR.Get(SRID.ParserDefaultConverterProperty, propType.FullName, propName, value);
                    } 
                    else 
                    {
                        // SomeText and there's no TypeConverter 
                        //  associated with the type SomeElement
                        message = SR.Get(SRID.ParserDefaultConverterElement, propType.FullName, value);
                    }
                    XamlParseException.ThrowException(parserContext, _lineNumber, _linePosition, message, null); 
                }
                else 
                { 
                    string message = TypeConverterFailure( value, propName, propType.FullName );
                    XamlParseException.ThrowException(parserContext, _lineNumber, _linePosition, message, e); 
                }
            }
#endif
 
            // Verify that the type converter actually gave us an instance of the correct object type.
            if( obj != null ) 
            { 
                if(!propType.IsAssignableFrom(obj.GetType()))
                { 
                    string message = TypeConverterFailure( value, propName, propType.FullName );

                    XamlParseException.ThrowException(parserContext, _lineNumber, _linePosition, message, null);
                } 
            }
 
            return obj; 
        }
 
        private string TypeConverterFailure( string value, string propName, string propType )
        {
            string message;
 
            if( propName != string.Empty )
            { 
                // We were called to do type conversion on a string that's been 
                //  assigned in an element attribute, but failed for whatever reason.
                // 
                //   
                //
                // propName is 'Fill' in this case.
 
                message = SR.Get(SRID.ParserCannotConvertPropertyValueString, value, propName, propType);
            } 
            else 
            {
                // We are being called by BamlRecordReader::GetObjectFromString 
                //  which is not trying to convert a property. It's actually
                //  trying to get an element out of this.
                //
                //   Red 
                //
                // There is no associated propName available in this case, so we 
                //  give a different error message. 

                message = SR.Get(SRID.ParserCannotConvertInitializationText, value, propType ); 
            }
            return message;
        }
#endif 

        // ValidateNames does Name validation, and ValidateEnums does enum 
        // name validation.  Note that both must be called to determine if a 
        // property is valid before it is set, but the order is not important.  Hence
        // ValidateNames can be called before writing out a BAML record, and 
        // ValidateEnums can be called later after the BAML record has been read.


        ///  
        /// Validate the Name property.
        /// This will throw an exception if the property is an 
        /// Name that does not follow the rules of only letters, digits and underscores in 
        /// Name names.
        ///  
        internal void ValidateNames(
            string   value,
            int      lineNumber,
            int      linePosition) 
        {
            // set the linenumber and position 
            _lineNumber = lineNumber; 
            _linePosition = linePosition;
 
            if (value == string.Empty)
            {
                ThrowException(SRID.ParserBadName, value);
            } 

            if (MarkupExtensionParser.LooksLikeAMarkupExtension(value)) 
            { 
                string message = SR.Get(SRID.ParserBadUidOrNameME, value);
                message += " "; 
                message += SR.Get(SRID.ParserLineAndOffset,
                            lineNumber.ToString(CultureInfo.CurrentCulture),
                            linePosition.ToString(CultureInfo.CurrentCulture));
 
                XamlParseException parseException = new XamlParseException(message, lineNumber, linePosition);
 
                throw parseException; 
            }
 
            if (!NameValidationHelper.IsValidIdentifierName(value))
            {
                ThrowException(SRID.ParserBadName, value);
            } 
        }
 
        ///  
        /// Validate that if the type converter is
        /// for enums you can't pass numbers to it. 
        /// 
        internal void ValidateEnums(
            string        propName,
            Type          propType, 
            string        attribValue)
        { 
            if (propType.IsEnum && attribValue != string.Empty) 
            {
                // Handle enum strings of the form "one, two, three".  Check that 
                // each of the values does NOT start with a digit.  This doesn't
                // validate that the enum is correct, just that there are no digits
                // specified.
                bool lookingForComma = false; 
                for (int i = 0; i < attribValue.Length; i++)
                { 
                    if (!Char.IsWhiteSpace(attribValue[i])) 
                    {
                        if (lookingForComma) 
                        {
                            if (attribValue[i] == ',')
                            {
                                lookingForComma = false; 
                            }
                        } 
                        else if (Char.IsDigit(attribValue[i])) 
                        {
                            ThrowException(SRID.ParserNoDigitEnums, propName, attribValue); 
                        }
                        else
                        {
                            lookingForComma = true; 
                        }
                    } 
                } 
            }
        } 

        /// 
        /// Get cached member info for the property name.  This can be
        /// a PropertyInfo for the property or a MethodInfo for the static 
        /// setter.  This does not work for EventInfo, so don't call it.
        ///  
        /// Type of the owner of the property  
        /// Name of the property
        /// True if the caller wants the PropertyInfo for the 
        ///     case where both a MethodInfo and propertyInfo are cached for this property
        /// 
        /// The attribute info record retrieved from
        ///     the map table, if one is found.  
        /// 
        /// There is only one scenario under which two memberInfo need to be 
        /// cached for a given attribute. This is the case when there are both a 
        /// Clr wrapper and static Settor for a given DP. In that case we cache
        /// an object array of two elements. Also the MethodInfo for the given DP 
        /// will be discovered first by the XamlReaderHelper while the PropertyInfo
        /// will be discovered by the BamlRecordWriter.
        /// 
        private MemberInfo GetCachedMemberInfo( 
               Type                    owner,
               string                  propName, 
               bool                    onlyPropInfo, 
           out BamlAttributeInfoRecord infoRecord)
        { 
            infoRecord = null;
            if (MapTable != null)
            {
                string fullName = owner.IsGenericType ? owner.Namespace + "." + owner.Name : owner.FullName; 
                object key = MapTable.GetAttributeInfoKey(fullName, propName);
                infoRecord = MapTable.GetHashTableData(key) as BamlAttributeInfoRecord; 
 
                if (infoRecord != null)
                { 
                    return infoRecord.GetPropertyMember(onlyPropInfo) as MemberInfo;
                }
            }
            return null; 
        }
 
#if !PBTCOMPILER 
        /// 
        /// Add cached member info for the property name. 
        /// 
        private void AddCachedAttributeInfo(
               Type                    ownerType,
               BamlAttributeInfoRecord infoRecord) 
        {
            if (MapTable != null) 
            { 
                object key = MapTable.GetAttributeInfoKey(ownerType.FullName, infoRecord.Name);
                MapTable.AddHashTableData(key, infoRecord); 
            }
        }

        ///  
        /// Helper function for getting Clr PropertyInfo on a type and updating the
        /// passed attribute info record.  Also update the property cache with this 
        /// attribute information if it was not already present. 
        /// 
        ///  
        /// Note that the ObjectHashTable may contain
        /// a BamlAttributeInfoRecord from a previous parse for the same property.  If
        /// we find one in the hash table, use its property info instead of reflecting.
        ///  
        internal void UpdateClrPropertyInfo(
            Type currentParentType, 
            BamlAttributeInfoRecord attribInfo) 
        {
            Debug.Assert(null != attribInfo, "null attribInfo"); 
            Debug.Assert(null != currentParentType, "null currentParentType");

            bool isInternal = false;
            string propName = attribInfo.Name; 

            BamlAttributeInfoRecord cachedInfoRecord; 
            attribInfo.PropInfo = GetCachedMemberInfo(currentParentType, propName, true, out cachedInfoRecord) 
                as PropertyInfo;
 
            if (attribInfo.PropInfo == null)
            {
                // If no cached property info, use the slow route of reflecting to get
                // the property info. 
                attribInfo.PropInfo = PropertyInfoFromName(propName, currentParentType, !ReflectionHelper.IsPublicType(currentParentType), false, out isInternal);
                attribInfo.IsInternal = isInternal; 
                if (attribInfo.PropInfo != null) 
                {
                    // If we successfully find a property info via reflection, cache it. 
                    if (cachedInfoRecord != null)
                    {
                        cachedInfoRecord.SetPropertyMember(attribInfo.PropInfo);
                        cachedInfoRecord.IsInternal = attribInfo.IsInternal; 
                    }
                    else 
                    { 
                        AddCachedAttributeInfo(currentParentType, attribInfo);
                    } 
                }
            }
            else
            { 
                attribInfo.IsInternal = cachedInfoRecord.IsInternal;
            } 
        } 

        private void UpdateAttachedPropertyMethdodInfo(BamlAttributeInfoRecord attributeInfo, bool isSetter) 
        {
            MethodInfo attachedPropertyInfo = null;
            Type propertyOwnerType = attributeInfo.OwnerType;
            Debug.Assert(propertyOwnerType != null); 
            bool tryInternal = !ReflectionHelper.IsPublicType(propertyOwnerType);
            string propName = (isSetter ? "Set" : "Get") + attributeInfo.Name; 
            BindingFlags flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy; 

            // Check Set\GetFoo method presence 

            try
            {
                if (!tryInternal) 
                {
                    // first try public methods 
                    attachedPropertyInfo = propertyOwnerType.GetMethod(propName, flags); 
                }
 
                if (attachedPropertyInfo == null)
                {
                    // if public method not found, try non-public method next.
                    attachedPropertyInfo = propertyOwnerType.GetMethod(propName, flags | BindingFlags.NonPublic); 
                }
            } 
            catch (AmbiguousMatchException) 
            {
            } 

            int paramCount = isSetter ? 2 : 1;
            if (attachedPropertyInfo != null && attachedPropertyInfo.GetParameters().Length == paramCount)
            { 
                // the MethodInfo has to be public or internal.
                Debug.Assert(attachedPropertyInfo.IsPublic || 
                                 attachedPropertyInfo.IsAssembly || 
                                 attachedPropertyInfo.IsFamilyOrAssembly);
 
                if (isSetter)
                {
                    attributeInfo.AttachedPropertySetter = attachedPropertyInfo;
                } 
                else
                { 
                    attributeInfo.AttachedPropertyGetter = attachedPropertyInfo; 
                }
            } 
        }

        internal void UpdateAttachedPropertySetter(BamlAttributeInfoRecord attributeInfo)
        { 
            if (attributeInfo.AttachedPropertySetter == null)
            { 
                UpdateAttachedPropertyMethdodInfo(attributeInfo, true); 
            }
        } 

        internal void UpdateAttachedPropertyGetter(BamlAttributeInfoRecord attributeInfo)
        {
            if (attributeInfo.AttachedPropertyGetter == null) 
            {
                UpdateAttachedPropertyMethdodInfo(attributeInfo, false); 
            } 
        }
 
#endif

        /// 
        /// Common helper method to resolve an xml XmlNamespace and LocalName to 
        /// either a EventInfo or a PropertyInfo.
        ///  
        /// True if Event, False look for Property 
        /// Type we should look for attribute on, can be null
        /// XmlNamespace or the Attribute 
        /// local Name of the Attribute
        /// Name of the resolved property or event
        /// PropertyInfo or EventInfo for resolved property or event
        internal MemberInfo GetClrInfo( 
                bool   isEvent,
                Type   owner, 
                string xmlNamespace, 
                string localName,
            ref string propName) 
        {
            Debug.Assert(null != localName, "null localName");
            Debug.Assert(null != xmlNamespace, "null xmlNamespace");
 
            // adjust urtNamespace and localName if there are any periods in the localName.
            string globalClassName = null; 
            int lastIndex = localName.LastIndexOf('.'); 

            if (-1 != lastIndex) 
            {
                // If using .net then match against the class.
                globalClassName = localName.Substring(0, lastIndex);
                localName = localName.Substring(lastIndex+1); 
            }
 
            return GetClrInfoForClass(isEvent, owner, xmlNamespace, localName, globalClassName, ref propName); 
        }
 
#if PBTCOMPILER
        // Checks to see if a given event handler delegate type is accessible.
        static private bool IsAllowedEventDelegateType(Type delegateType)
        { 
            if (!ReflectionHelper.IsPublicType(delegateType))
            { 
                if (!ReflectionHelper.IsInternalType(delegateType) || 
                    !IsInternalAllowedOnType(delegateType))
                { 
                    return false;
                }
            }
 
            return true;
        } 
 
        // Checks to see if a given event's add method is accessible.
        // Checks for protected add methods as well if requested. 
        private bool IsAllowedEvent(EventInfo ei, bool isProtectedAllowed)
        {
            MethodInfo mi = ei.GetAddMethod(true);
            return IsAllowedMethod(mi, isProtectedAllowed); 
        }
 
        // Checks to see if a given property's set method is accessible. 
        // Always checks for protected set methods as well.
        internal bool IsAllowedPropertySet(PropertyInfo pi) 
        {
            MethodInfo mi = pi.GetSetMethod(true);
            return IsAllowedMethod(mi, true);
        } 

        // Checks to see if a given property's get method is accessible. 
        // Checks for protected get methods as well if requested. 
        private bool IsAllowedPropertyGet(PropertyInfo pi, bool checkProtected)
        { 
            MethodInfo mi = pi.GetGetMethod(true);
            return IsAllowedMethod(mi, checkProtected);
        }
 
        // Checks to see if a given property's get method is accessible.
        // Always checks for protected get methods as well. 
        internal bool IsAllowedPropertyGet(PropertyInfo pi) 
        {
            MethodInfo mi = pi.GetGetMethod(true); 
            return IsAllowedMethod(mi, true);
        }

        // Checks to see if a given field member is accessible. 
        private bool IsAllowedField(FieldInfo fi)
        { 
            bool allowed = false; 

            // No field, so not allowed 
            if (fi != null)
            {
                // field is public -- always allow.
                allowed = fi.IsPublic; 
                if (!allowed)
                { 
                    // if not, try accessible internal fields. 
                    // if the field from a base type, then it must be in the same assembly
                    // as the type from which it was reflected. If not, internals will not 
                    // be allowed.
                    if (fi.ReflectedType.Assembly == fi.DeclaringType.Assembly)
                    {
                        // if reflected type is public, check to see if internals are allowed 
                        // on that type (i.e local or friend). If not, the type has to be an
                        // internal allowed type due to the guaranteed central check in 
                        // CreateTypeAndSerializer(). 
                        if (ReflectionHelper.IsPublicType(fi.ReflectedType))
                        { 
                            allowed = IsInternalAllowedOnType(fi.ReflectedType);
                        }
                        else
                        { 
                            allowed = true;
                        } 
 
                        // Either ways, if reflected type is allowed only allow non-public
                        // fields that are internal. 
                        allowed = allowed && (fi.IsAssembly || fi.IsFamilyOrAssembly);
                    }
                }
            } 

            return allowed; 
        } 

        // Checks to see if a given methodInfo (for a property's get\set method 
        // or an event's add method) is accessible.
        private bool IsAllowedMethod(MethodInfo mi, bool checkProtected)
        {
            bool allowed = false; 

            // No method, so not allowed 
            if (mi != null) 
            {
                // method is public -- always allow. 
                allowed = mi.IsPublic;
                if (!allowed)
                {
                    // method is not public. 
                    // Next check to see if the mapper will allow looking for protected
                    // attributes. This will be the case if current methodInfo has been 
                    // reflected off of the markup sub-classed root element, i.e one with 
                    // an x:Class attribute, in which case IsProtectedAttributeAllowed will
                    // be true. So in this case allow protected if caller wishes for this 
                    // by setting the checkProtected param to true.
                    if (checkProtected && IsProtectedAttributeAllowed)
                    {
                        // if so, allow protected or internal protected method. 
                        allowed = mi.IsFamily || mi.IsFamilyOrAssembly;
                    } 
 
                    if (!allowed)
                    { 
                        // if not, try accessible internal methods.
                        // if the property or event inherits from a base type, then its
                        // accessor method must be in the same assembly as the type from
                        // which it was reflected. If not, internals will not be allowed. 
                        if (mi.ReflectedType.Assembly == mi.DeclaringType.Assembly)
                        { 
                            // if reflected type is public, check to see if internals are allowed 
                            // on that type (i.e local or friend). If not, the type has to be an
                            // internal allowed type due to the guaranteed central check in 
                            // CreateTypeAndSerializer().
                            if (ReflectionHelper.IsPublicType(mi.ReflectedType))
                            {
                                allowed = IsInternalAllowedOnType(mi.ReflectedType); 
                            }
                            else 
                            { 
                                allowed = true;
                            } 

                            // Either ways, if reflected type is allowed only allow non-public members
                            // that are internal.
                            allowed = allowed && (mi.IsAssembly || mi.IsFamilyOrAssembly); 
                        }
                    } 
                } 
            }
 
            return allowed;
        }
#else
        // Checks to see if a given property's set method is public. 
        // Used only in Xaml Load sceanrios.
        internal bool IsAllowedPropertySet(PropertyInfo pi) 
        { 
            MethodInfo mi = pi.GetSetMethod(true);
            return (mi != null && mi.IsPublic); 
        }

        // Checks to see if a given property's get method is public.
        // Used only in Xaml Load sceanrios. 
        internal bool IsAllowedPropertyGet(PropertyInfo pi)
        { 
            MethodInfo mi = pi.GetGetMethod(true); 
            return (mi != null && mi.IsPublic);
        } 

        // Checks to see if a given property's set method is accessible.
        // Used only in compiled Baml Load sceanrios.
        static internal bool IsAllowedPropertySet(PropertyInfo pi, bool allowProtected, out bool isPublic) 
        {
            MethodInfo mi = pi.GetSetMethod(true); 
            bool isProtected = allowProtected && mi != null && mi.IsFamily; 
            // return isPublic == true only if the property is public on a base declaring Type.
            // if the property is public on the reflected internal type itself, then we still 
            // need to call the generated helper to set the property.
            isPublic = mi != null && mi.IsPublic && ReflectionHelper.IsPublicType(mi.DeclaringType);
            return (mi != null && (mi.IsPublic || mi.IsAssembly || mi.IsFamilyOrAssembly || isProtected));
        } 

        // Checks to see if a given property's get method is accessible. 
        // Used only in compiled Baml Load sceanrios. 
        static private bool IsAllowedPropertyGet(PropertyInfo pi, bool allowProtected, out bool isPublic)
        { 
            MethodInfo mi = pi.GetGetMethod(true);
            bool isProtected = allowProtected && mi != null && mi.IsFamily;
            // return isPublic == true only if the property is public on a base declaring Type.
            // if the property is public on the reflected internal type itself, then we still 
            // need to call the generated helper to get the property.
            isPublic = mi != null && mi.IsPublic && ReflectionHelper.IsPublicType(mi.DeclaringType); 
            return (mi != null && (mi.IsPublic || mi.IsAssembly || mi.IsFamilyOrAssembly || isProtected)); 
        }
 
        // Checks to see if a given event's add method is accessible.
        // Used only in compiled Baml Load sceanrios.
        static private bool IsAllowedEvent(EventInfo ei, bool allowProtected, out bool isPublic)
        { 
            MethodInfo mi = ei.GetAddMethod(true);
            bool isProtected = allowProtected && mi != null && mi.IsFamily; 
            // return isPublic == true only if the event is public on a base declaring Type. 
            // if the event is public on the reflected internal type itself, then we still
            // need to call the generated helper to hook up the event. 
            isPublic = mi != null && mi.IsPublic && ReflectionHelper.IsPublicType(mi.DeclaringType);
            return (mi != null && (mi.IsPublic || mi.IsAssembly || mi.IsFamilyOrAssembly || isProtected));
        }
#endif 

        // Checks to see if a given event's add method is public. 
        // Used in all (xaml load, xaml compile & compiled Baml Load sceanrios. 
        static private bool IsPublicEvent(EventInfo ei)
        { 
            MethodInfo mi = ei.GetAddMethod(true);
            return (mi != null && mi.IsPublic);
        }
 
#if !PBTCOMPILER
        ///  
        /// Allows a sub-classed XamlTypeMapper called under Full Trust to participate 
        /// in deciding if an internal type should be accessible.
        ///  
        /// The internal type
        /// 
        /// When overriden, should return true if accessible, false if not.
        /// Returns false by default, if no one overrides. 
        /// 
        protected virtual bool AllowInternalType(Type type) 
        { 
            return false;
        } 

        private bool IsInternalTypeAllowedInFullTrust(Type type)
        {
            bool isAllowed = false; 
            // If caller has Full Trust and the type is internal, then allow them to participate
            // in deciding if that internal type should be accessible. 
            if (ReflectionHelper.IsInternalType(type) && MS.Internal.SecurityHelper.IsFullTrustCaller()) 
            {
                isAllowed = AllowInternalType(type); 
            }

            return isAllowed;
        } 
#endif
 
        ///  
        /// Common helper method to resolve an xml XmlNamespace and LocalName to
        /// either a EventInfo or a PropertyInfo. 
        /// 
        /// True if Event, False look for Property
        /// Type we should look for attribute on, can be null
        /// XmlNamespace or the Attribute 
        /// local Name of the Attribute with no class
        /// Class Name of the Attribute, or null if not present 
        /// Name of the resolved property or event 
        /// PropertyInfo or EventInfo for resolved property or event
        internal MemberInfo GetClrInfoForClass ( 
                bool   isEvent,
                Type   owner,
                string xmlNamespace,
                string localName, 
                string globalClassName,
            ref string propName) 
        { 
            MemberInfo mi = null;
#if PBTCOMPILER 
            if (owner == null || ReflectionHelper.IsPublicType(owner))
            {
#endif
            // first, try normal lookup for public properties and events only. 
                mi = GetClrInfoForClass(isEvent, owner, xmlNamespace, localName, globalClassName, false, ref propName);
#if PBTCOMPILER 
            } 

            if (mi == null && owner != null) 
            {
                // if lookup on internal type or if public property or event lookup failed,
                // try internal ones as well, or protected if the type happens to be a
                // code-generated root. 
                mi = GetClrInfoForClass(isEvent, owner, xmlNamespace, localName, globalClassName, true, ref propName);
            } 
#endif 

            return mi; 
        }

        private MemberInfo GetClrInfoForClass(
                bool isEvent, 
                Type owner,
                string xmlNamespace, 
                string localName, 
                string globalClassName,
                bool tryInternal, 
            ref string propName)
        {
            bool isInternal = false;
            MemberInfo memberInfo = null; 
            BindingFlags defaultBinding = BindingFlags.Public;
 
#if PBTCOMPILER 
            if (tryInternal)
            { 
                defaultBinding |= BindingFlags.NonPublic;
            }
#endif
 
            propName = null;
            ParameterInfo[] pis = null; 
 
            // if this is a globalClass then resolve the type and then call the dpFromName
            if (null != globalClassName) 
            {
                TypeAndSerializer typeAndSerializer =
                    GetTypeOnly(xmlNamespace, globalClassName);
 
                if (typeAndSerializer != null && typeAndSerializer.ObjectType != null)
                { 
                    BamlAttributeInfoRecord infoRecord; 
                    Type objectType = typeAndSerializer.ObjectType;
                    memberInfo = GetCachedMemberInfo(objectType, localName, false, out infoRecord); 

                    if (memberInfo == null)
                    {
                        if (isEvent) 
                        {
                            // See if attached event first 
                            memberInfo = objectType.GetMethod("Add" + localName + "Handler", 
                                defaultBinding |
                                BindingFlags.Static | 
                                BindingFlags.FlattenHierarchy);

                            // Make sure that we found a method of the right signature.
                            // Otherwise discard what you found. 
                            if (memberInfo != null)
                            { 
                                MethodInfo mi = memberInfo as MethodInfo; 
                                if (mi != null)
                                { 
                                    pis = mi.GetParameters();
                                    Type dependencyObjectType = KnownTypes.Types[(int)KnownElements.DependencyObject];
                                    if (pis == null || pis.Length != 2 || !dependencyObjectType.IsAssignableFrom(pis[0].ParameterType))
                                    { 
                                        memberInfo = null;
                                    } 
#if PBTCOMPILER 
                                    if (tryInternal && memberInfo != null && !IsAllowedMethod(mi, false))
                                    { 
                                        ThrowException(SRID.ParserCantSetAttribute, "bubbling event", objectType.Name + "." + localName, "Add Handler method");
                                    }
#endif
                                } 
                            }
 
                            // 
                            if (memberInfo == null)
                            { 
                                // Not an attached event so try Clr event
                                memberInfo = objectType.GetEvent(localName,
                                    defaultBinding |
                                    BindingFlags.Instance | 
                                    BindingFlags.FlattenHierarchy);
 
                                if (memberInfo != null) 
                                {
                                    EventInfo ei = memberInfo as EventInfo; 
#if PBTCOMPILER
                                    if (!IsAllowedEventDelegateType(ei.EventHandlerType))
#else
                                    if (!ReflectionHelper.IsPublicType(ei.EventHandlerType)) 
#endif
                                    { 
                                        ThrowException(SRID.ParserEventDelegateTypeNotAccessible, ei.EventHandlerType.FullName, objectType.Name + "." + localName); 
                                    }
 
#if PBTCOMPILER
                                    if (tryInternal)
                                    {
                                        // Check if the event add method accessor itself is accessible. 
                                        // Also if this is a non-public event on a public type, it will
                                        // check to make sure that the public type is accessible\allowed. 
                                        if (!IsAllowedEvent(ei, false)) 
                                        {
                                            ThrowException(SRID.ParserCantSetAttribute, "event", objectType.Name + "." + localName, "add"); 
                                        }
                                    }
                                    else
                                    { 
#endif
                                        // Check if the event add method accessor itself is public. 
                                        if (!IsPublicEvent(ei)) 
                                        {
#if PBTCOMPILER 
                                            memberInfo = null;
#else
                                            ThrowException(SRID.ParserCantSetAttribute, "event", objectType.Name + "." + localName, "add");
#endif 
                                        }
#if PBTCOMPILER 
                                    } 
#endif
                                } 
                            }
                        }
                        else
                        { 

                            // See if attached property first - start from a Setter 
                            memberInfo = objectType.GetMethod("Set" + localName, 
                                defaultBinding |
                                BindingFlags.Static | 
                                BindingFlags.FlattenHierarchy);
                            if (memberInfo != null && ((MethodInfo)memberInfo).GetParameters().Length != 2)
                            {
                                memberInfo = null; 
                            }
                            // Try read-only case (Getter only) 
                            if (memberInfo == null) 
                            {
                                memberInfo = objectType.GetMethod("Get" + localName, 
                                    defaultBinding |
                                    BindingFlags.Static |
                                    BindingFlags.FlattenHierarchy);
                                if (memberInfo != null && ((MethodInfo)memberInfo).GetParameters().Length != 1) 
                                {
                                    memberInfo = null; 
                                } 
                            }
 
#if PBTCOMPILER
                            if (tryInternal && memberInfo != null && !IsAllowedMethod(memberInfo as MethodInfo, false))
                            {
                                ThrowException(SRID.ParserCantSetAttribute, "attached property", objectType.Name + "." + localName, "Set method"); 
                            }
#endif 
 
                            //
                            if (memberInfo == null) 
                            {
                                // Not an attached property, so try clr property
                                memberInfo = PropertyInfoFromName(localName, objectType, tryInternal, true, out isInternal);
 
                                // If we've found a property info, then the owner had better
                                // be the same type as or a subclass of the objectType, or 
                                // they are in different inheritance hierarchies.  This 
                                // fixes windows bug 920135.
                                if (memberInfo != null) 
                                {
                                    if (owner != null &&
                                        !objectType.IsAssignableFrom(owner))
                                    { 
                                        ThrowException(SRID.ParserAttachedPropInheritError,
                                                       String.Format(CultureInfo.CurrentCulture, "{0}.{1}", objectType.Name, localName), 
                                                       owner.Name); 
                                    }
                                } 
                            }

                            if (null != memberInfo)
                            { 
                                if (infoRecord != null)
                                { 
#if !PBTCOMPILER 
                                    // DP's aren't present in the PBT case
                                    if (infoRecord.DP == null) 
                                    {
                                        infoRecord.DP = MapTable.GetDependencyProperty(infoRecord);
                                    }
#endif 
                                    infoRecord.SetPropertyMember(memberInfo);
                                } 
                            } 
                        }
                    } 
                }
            }
            else if (null != owner)
            { 
                Type baseType = owner;
 
                // See if the owner knows about this class. 
                // Look for a parent type until we find a match or fail.
                if (null != baseType) 
                {
                    BamlAttributeInfoRecord infoRecord;
                    memberInfo = GetCachedMemberInfo(baseType, localName, false, out infoRecord);
 
                    if (memberInfo == null)
                    { 
                        if (isEvent) 
                        {
                            // See if attached event first 
                            memberInfo = baseType.GetMethod("Add" + localName + "Handler",
                                defaultBinding | BindingFlags.Static | BindingFlags.FlattenHierarchy);

                            // Make sure that we found a method of the right signature. 
                            // Otherwise discard what you found.
                            if (memberInfo != null) 
                            { 
                                MethodInfo mi = memberInfo as MethodInfo;
                                if (mi != null) 
                                {
                                    pis = mi.GetParameters();
                                    Type dependencyObjectType = KnownTypes.Types[(int)KnownElements.DependencyObject];
                                    if (pis == null || pis.Length != 2 || !dependencyObjectType.IsAssignableFrom(pis[0].ParameterType)) 
                                    {
                                        memberInfo = null; 
                                    } 
#if PBTCOMPILER
                                    if (tryInternal && memberInfo != null && !IsAllowedMethod(mi, true)) 
                                    {
                                        ThrowException(SRID.ParserCantSetAttribute, "bubbling event", owner.Name + "." + localName, "Add Handler method");
                                    }
#endif 
                                }
                            } 
 
                            if (memberInfo == null)
                            { 
                                // Not an attached event, so try for a clr event.
                                memberInfo = baseType.GetEvent(localName,
                                    BindingFlags.Instance | BindingFlags.FlattenHierarchy | defaultBinding);
 
                                if (memberInfo != null)
                                { 
                                    EventInfo ei = memberInfo as EventInfo; 
#if PBTCOMPILER
                                    if (!IsAllowedEventDelegateType(ei.EventHandlerType)) 
#else
                                    if (!ReflectionHelper.IsPublicType(ei.EventHandlerType))
#endif
                                    { 
                                        ThrowException(SRID.ParserEventDelegateTypeNotAccessible, ei.EventHandlerType.FullName, owner.Name + "." + localName);
                                    } 
 
#if PBTCOMPILER
                                    if (tryInternal) 
                                    {
                                        // Check if the event add method accessor itself is accessible.
                                        // Also if this is a non-public event on a public type, it will
                                        // not check to make sure that the public type is accessible\allowed 
                                        // since that would have all ready been done in the caller of this fucntion.
                                        if (!IsAllowedEvent(ei, true)) 
                                        { 
                                            ThrowException(SRID.ParserCantSetAttribute, "event", owner.Name + "." + localName, "add");
                                        } 
                                    }
                                    else
                                    {
#endif 
                                        // check if the event add method accessor itself is public.
                                        if (!IsPublicEvent(ei)) 
                                        { 
#if PBTCOMPILER
                                            memberInfo = null; 
#else
                                            ThrowException(SRID.ParserCantSetAttribute, "event", owner.Name + "." + localName, "add");
#endif
                                        } 
#if PBTCOMPILER
                                    } 
#endif 
                                }
                            } 
                        }
                        else
                        {
                            // See if attached property first - start from a Setter 
                            memberInfo = baseType.GetMethod("Set" + localName,
                                defaultBinding | 
                                BindingFlags.Static | 
                                BindingFlags.FlattenHierarchy);
                            if (memberInfo != null && ((MethodInfo)memberInfo).GetParameters().Length != 2) 
                            {
                                memberInfo = null;
                            }
                            // Try read-only case (Getter only) 
                            if (memberInfo == null)
                            { 
                                memberInfo = baseType.GetMethod("Get" + localName, 
                                    defaultBinding |
                                    BindingFlags.Static | 
                                    BindingFlags.FlattenHierarchy);
                                if (memberInfo != null && ((MethodInfo)memberInfo).GetParameters().Length != 1)
                                {
                                    memberInfo = null; 
                                }
                            } 
 
#if PBTCOMPILER
                            if (tryInternal && memberInfo != null && !IsAllowedMethod(memberInfo as MethodInfo, true)) 
                            {
                                ThrowException(SRID.ParserCantSetAttribute, "attached property", owner.Name + "." + localName, "Set method");
                            }
#endif 

                            if (memberInfo == null) 
                            { 
                                // Not an attached property, so try for a clr property.
                                memberInfo = PropertyInfoFromName(localName, baseType, tryInternal, true, out isInternal); 
                            }

                            if (null != memberInfo)
                            { 
                                if (infoRecord != null)
                                { 
#if !PBTCOMPILER 
                                    // DP's aren't present in the PBT case
                                    if (infoRecord.DP == null) 
                                    {
                                        infoRecord.DP = MapTable.GetDependencyProperty(infoRecord);
                                    }
#endif 
                                    infoRecord.SetPropertyMember(memberInfo);
                                } 
                            } 
                        }
                    } 
                }
            }

            if (null != memberInfo) 
            {
                propName = localName; 
            } 

            return memberInfo; 
        }

#if !PBTCOMPILER
        ///  
        /// Helper method to get an event on an owner, walking up the class hierarchy
        /// when doing so 
        ///  
        /// Type we should look for the event on
        /// Then name of the handler of the event 
        /// EventInfo for resolved event
        internal EventInfo GetClrEventInfo(
            Type   owner,
            string eventName) 
        {
            Debug.Assert(null != eventName, "null eventName"); 
            Debug.Assert(null != owner, "null owner"); 

            EventInfo eventInfo = null; 

            // Look up the parent chain until we find a match or fail by
            // going off the top of the chain.
            while (owner != null) 
            {
                eventInfo = owner.GetEvent(eventName, BindingFlags.Instance | BindingFlags.Public); 
                if (eventInfo != null) 
                {
                    break; 
                }

                owner = GetCachedBaseType(owner);
            } 

            return eventInfo; 
        } 

        ///  
        /// Helper method to resolve an xml namespace and localName to
        /// either a RoutedEvent or a DependencyProperty.  If they are not present,
        /// still resolve using a guess at the valid setter name to look for.
        ///  
        /// 
        ///  Note that this will not resolve clr properties.  Call GetClrInfo to do that. 
        ///  
        /// True if Event, False look for Property
        /// Type we should look for attribute on, can be null 
        /// XmlNamespace or the Attribute
        /// local Name of the Attribute
        /// Base type the object was found on
        /// registered name of the Object on the type. 
        /// resolved object, which can be a RoutedEvent, a DependencyProperty
        ///          or the MethodInfo for the event or property setter 
        internal object GetDependencyObject( 
                bool       isEvent,
                Type       owner, 
                string     xmlNamespace,
                string     localName,
            ref Type       baseType,
            ref string     dynamicObjectName) 
        {
            Debug.Assert(null != localName, "null localName"); 
            Debug.Assert(null != xmlNamespace, "null xmlNamespace"); 

            object memInfo = null; 
            string globalClassName = null;

            dynamicObjectName = null;
 
            // Extract the class name if there are any periods in the localName.
            int lastIndex = localName.LastIndexOf('.'); 
            if (-1 != lastIndex) 
            {
                // if using .net then match against the class. 
                globalClassName = localName.Substring(0,lastIndex);
                localName = localName.Substring(lastIndex+1);
            }
 
            // If this is a globalClassName then resolve the type and then call
            // DependencyProperty.FromName. 
            if (null != globalClassName) 
            {
                TypeAndSerializer typeAndSerializer = 
                    GetTypeOnly(xmlNamespace,globalClassName);

                if (typeAndSerializer != null && typeAndSerializer.ObjectType != null)
                { 
                    baseType = typeAndSerializer.ObjectType;
                    if (isEvent) 
                    { 
                        memInfo = RoutedEventFromName(localName,baseType);
                    } 
                    else
                    {
                        memInfo = DependencyProperty.FromName(localName, baseType);
 
                    }
 
                    if (null != memInfo) 
                    {
                        Debug.Assert(null != baseType, "baseType not set"); 
                        dynamicObjectName = localName;
                    }
                }
            } 
            else
            { 
                NamespaceMapEntry[] namespaceMaps = GetNamespaceMapEntries(xmlNamespace); 

                if (null == namespaceMaps) 
                {
                    return null;
                }
 
                baseType = owner;
 
                // See if the owner knows about this class. 
                // Look for a parent type with any namespace matching the property
                while (null != baseType) 
                {
                    bool foundNamespaceMatch = false;

                    // Look at each namespace for a match with this baseType 
                    for (int count = 0;
                         count < namespaceMaps.Length && !foundNamespaceMatch; 
                         count ++) 
                    {
                        NamespaceMapEntry namespaceMap = namespaceMaps[count]; 

                        // see if the urtNamespace in the namespace map is valid
                        // for the type we are trying to apply
                        if (namespaceMap.ClrNamespace == GetCachedNamespace(baseType)) 
                        {
                            foundNamespaceMatch = true; 
                        } 
                    }
 
                    if (foundNamespaceMatch)
                    {
                        // For 'normal' properties and events that are not prefixed by
                        // a class name, only attempt to get dependency IDs and Events. 
                        // The caller should use GetClrInfo to get CLR properties for
                        // 'normal' properties and events if this attempt fails. 
                        if (isEvent) 
                        {
                            memInfo = RoutedEventFromName(localName,baseType); 
                        }
                        else
                        {
                            memInfo = DependencyProperty.FromName(localName, baseType); 
                        }
                    } 
 
                    // Only do one loop for events, since all base classes are checked in
                    // a single operation.  For properties, loop through the base classes here. 
                    if (null != memInfo || isEvent)
                    {
                        // for assembly and typeName use the original, not the base
                        // type we found it on. 
                        dynamicObjectName = localName;
                        break; 
                    } 
                    else
                    { 
                        baseType = GetCachedBaseType(baseType);
                    }
                }
            } 

            return memInfo; 
        } 

 
         ///
        /// Returns a DependencyProperty given a local name and an xml namespace
        ///
        /// 
        /// The property name
        /// 
        /// 
        /// Xml namespace associated with name
        /// 
        ///
        /// The Type where this DP was registered.
        ///
        /// 
        /// Returns a DependencyProperty the attached property
        /// 
        internal DependencyProperty DependencyPropertyFromName( 
                string localName,
                string xmlNamespace, 
            ref Type   ownerType)
         {
             Debug.Assert(null != localName, "null localName");
             Debug.Assert(null != xmlNamespace, "null xmlNamespace"); 

            // Adjust localName if there are any periods that indicate a global class.  Use 
            // this class name as the owner type and return it.  Otherwise just use the 
            // passed name and owner.
            int lastIndex = localName.LastIndexOf('.'); 
            if (-1 != lastIndex)
            {
                string globalClassName = localName.Substring(0,lastIndex);
                localName = localName.Substring(lastIndex+1); 
                TypeAndSerializer typeAndSerializer =
                    GetTypeOnly(xmlNamespace, globalClassName); 
                if (typeAndSerializer == null || typeAndSerializer.ObjectType == null) 
                {
                    ThrowException(SRID.ParserNoType, globalClassName); 
                }
                ownerType = typeAndSerializer.ObjectType;
            }
 
            if(null == ownerType)
            { 
                throw new ArgumentNullException( "ownerType" ); 
            }
 
            return DependencyProperty.FromName(localName, ownerType);
        }

#endif 

        ///  
        /// Return the property that has an attached XmlLang attribute.  This identifies this 
        /// property as being the one to receive xml:lang attribute values when parsing, or
        /// the holder of the CultureInfo related string.  The XamlTypeMapper caches this 
        /// along with the TypeAndSerializer information for fast retrieval.
        /// 
        internal PropertyInfo GetXmlLangProperty(
                string    xmlNamespace,     // xml namespace for the type 
                string    localName)        // local name of the type without any '.'
        { 
            TypeAndSerializer typeAndSerializer = GetTypeOnly(xmlNamespace, localName); 

            if (typeAndSerializer == null || typeAndSerializer.ObjectType == null) 
            {
                return null;
            }
 
            if (typeAndSerializer.XmlLangProperty == null)
            { 
                BamlAssemblyInfoRecord bairPF = MapTable.GetAssemblyInfoFromId(-1); 

                if (typeAndSerializer.ObjectType.Assembly == bairPF.Assembly) 
                {
                    if (KnownTypes.Types[(int)KnownElements.FrameworkElement].IsAssignableFrom(typeAndSerializer.ObjectType) ||
                        KnownTypes.Types[(int)KnownElements.FrameworkContentElement].IsAssignableFrom(typeAndSerializer.ObjectType))
                    { 
                        typeAndSerializer.XmlLangProperty = (KnownTypes.Types[(int)KnownElements.FrameworkElement]).GetProperty("Language",
                            BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy); 
                    } 
                }
                else 
                {
                    string xmlLangPropertyName = null;
                    bool   xmlLangPropertyFound = false;
 
#if !PBTCOMPILER
                    AttributeCollection attributes = TypeDescriptor.GetAttributes(typeAndSerializer.ObjectType); 
 
                    if (attributes != null)
                    { 
                        XmlLangPropertyAttribute xlpa = attributes[typeof(XmlLangPropertyAttribute)] as XmlLangPropertyAttribute;
                        if (xlpa != null)
                        {
                            xmlLangPropertyFound = true; 
                            xmlLangPropertyName = xlpa.Name;
                        } 
                    } 
#else
                    Type typeValue = null; 
                    xmlLangPropertyName = ReflectionHelper.GetCustomAttributeData(typeAndSerializer.ObjectType,
                                                                                  KnownTypes.Types[(int)KnownElements.XmlLangPropertyAttribute],
                                                                                  false,
                                                                              ref xmlLangPropertyFound, 
                                                                              out typeValue);
#endif 
 
                    if ( xmlLangPropertyFound )
                    { 
                        if( xmlLangPropertyName != null && xmlLangPropertyName.Length > 0)
                        {
                            typeAndSerializer.XmlLangProperty = typeAndSerializer.ObjectType.GetProperty(
                                xmlLangPropertyName, 
                                BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
                        } 
 
                        if( typeAndSerializer.XmlLangProperty == null )
                        { 
                            // Either the given name could not be found, or there
                            //  was no name specified at all.  (null or empty string.)
                            // The latter case may get a special meaning in the future,
                            //  but for now they're all errors. 
                            ThrowException(SRID.ParserXmlLangPropertyValueInvalid);
                        } 
                    } 
                }
            } 

            return typeAndSerializer.XmlLangProperty;
        }
 
        ///
        /// Returns a PropertyInfo from an attribute name, given the ownerType of 
        /// the property. 
        ///
        /// 
        /// The attribute name
        ///
        ///
        /// The Type that owns the attribute 
        ///
        /// 
        /// Indicates if this function should search for non-public properties as well 
        ///
        /// 
        /// Indicates if this function should search for public properties only, regardless
        /// of tryInternal as is the case in XamlLoad sceanrios.
        ///
        /// 
        /// Indicates if this fucntion actually found a non-public property
        /// 
        /// 
        /// Returns a PropertyInfo for the property
        /// 
        private PropertyInfo PropertyInfoFromName(
            string localName,
            Type   ownerType,
            bool tryInternal, 
            bool tryPublicOnly,
            out bool isInternal) 
        { 
            PropertyInfo info = null;
            isInternal = false; 
            TypeInformationCacheData typeInfo = GetCachedInformationForType(ownerType);
            Debug.Assert(typeInfo != null, "Must have cached type info at this point");
            PropertyAndType propAndType = typeInfo.GetPropertyAndType(localName);
 
            // peterost - This is a TEMPORARY workaround to
            //    properties that have been overridden in some classes using the 
            //    "new" operator.  This should be removed when properties such as 
            //    Window.Width and ColumnDefintion.Width are rationalized.
            if (propAndType == null || !propAndType.PropInfoSet) 
            {
                try
                {
                    BindingFlags flags = BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.Public; 
#if PBTCOMPILER
                    if (tryInternal) 
                    { 
                        flags |= BindingFlags.NonPublic;
                    } 
                    info = ownerType.GetProperty(localName, flags);
#else
                    if (!tryInternal)
                    { 
                        info = ownerType.GetProperty(localName, flags);
                    } 
 
                    // Xaml load scenarios should not look for internals - tryPublicOnly == true
                    // If the above load failed then try again looking at internals, unless 
                    // tryPublicOnly tells us not to do that.
                    if (info == null && !tryPublicOnly)
                    {
                        info = ownerType.GetProperty(localName, flags | BindingFlags.NonPublic); 
                        if (info != null)
                        { 
                            isInternal = true; 
                        }
                    } 
#endif
                }
                catch (AmbiguousMatchException)
                { 
                    PropertyInfo[] infos = ownerType.GetProperties(
                                  BindingFlags.Instance | BindingFlags.Public); 
                    for (int i = 0; i < infos.Length; i++) 
                    {
                        if (infos[i].Name == localName) 
                        {
                            info = infos[i];
                            break;
                        } 
                    }
                } 
#if PBTCOMPILER 
                if (tryInternal || info != null)
                { 
#endif
                    typeInfo.SetPropertyAndType(localName, info, ownerType, isInternal);
#if PBTCOMPILER
                } 
#endif
            } 
            else 
            {
                info = propAndType.PropInfo; 
                isInternal = propAndType.IsInternal;
            }

            return info; 
        }
 
#if !PBTCOMPILER 

        /// 
        /// Returns a RoutedEvent from an attribute name
        ///
        ///
        /// The attribute name 
        ///
        /// 
        /// The Type that owns the attribute 
        ///
        /// 
        /// Returns a RoutedEvent for the name
        ///
        internal RoutedEvent RoutedEventFromName(
            string localName, 
            Type   ownerType)
        { 
            RoutedEvent Event = null; 
            Type currentType = ownerType;
 
            // Force load the Statics by walking up the hierarchy and running class constructors
            while (null != currentType)
            {
                MS.Internal.WindowsBase.SecurityHelper.RunClassConstructor(currentType); 
                currentType = GetCachedBaseType(currentType);
            } 
 
            // EventManager takes care of going up the hierarchy, so we don't need to loop here
            // to do it.  Just do one call. 
            Event =  EventManager.GetRoutedEventFromName(localName,ownerType);

            return Event;
       } 
#endif
 
        ///  
        /// Given an object that is either a PropertyInfo, MethodInfo for the static
        /// setter, or DependencyProperty, return the type of the property.  This assumes 
        /// the Avalon rule that a DependencyProperty has a static setter where the
        /// second parameter gives the type of the property.
        /// 
        internal static Type GetPropertyType(object propertyMember) 
        {
            Type propertyType; 
            bool propertyCanWrite; 
            GetPropertyType(propertyMember, out propertyType, out propertyCanWrite);
 
            return propertyType;
        }

        ///  
        /// Given an object that is either a PropertyInfo, MethodInfo for the static
        /// setter, or DependencyProperty, return the type of the property.  This assumes 
        /// the Avalon rule that a DependencyProperty has a static setter where the 
        /// second parameter gives the type of the property.
        ///  
        internal static void GetPropertyType(
            object propertyMember,
        out Type   propertyType,
        out bool   propertyCanWrite) 
        {
// 
#if !PBTCOMPILER 
            DependencyProperty dp = propertyMember as DependencyProperty;
            if (dp != null) 
            {
                propertyType = dp.PropertyType;
                propertyCanWrite = !dp.ReadOnly;
            } 
            else
            { 
#endif 
                PropertyInfo propertyInfo = propertyMember as PropertyInfo;
                if (propertyInfo != null) 
                {
                    propertyType = propertyInfo.PropertyType;
                    propertyCanWrite = propertyInfo.CanWrite;
                } 
                else
                { 
                    MethodInfo methodInfo = propertyMember as MethodInfo; 
                    if (methodInfo != null)
                    { 
                        ParameterInfo[] parameters = methodInfo.GetParameters();
                        propertyType = parameters.Length == 1 ? methodInfo.ReturnType : parameters[1].ParameterType;
                        propertyCanWrite = parameters.Length == 1 ? false : true;
                    } 
                    else
                    { 
                        // If its not a propertyinfo, methodinfo, or dependencyproperty, 
                        // all we know is that it must be an object...
                        propertyType = typeof(object); 
                        propertyCanWrite = false;
                    }
                }
#if !PBTCOMPILER 
            }
#endif 
        } 

 
        /// 
        /// Given an object that is either a PropertyInfo, MethodInfo for the static
        /// setter, or DependencyProperty, return the name of the property.  This assumes
        /// the Avalon rule that a DependencyProperty has a static getter "Get" + name. 
        /// 
        internal static string GetPropertyName(object propertyMember) 
        { 

#if !PBTCOMPILER 
            DependencyProperty dp = propertyMember as DependencyProperty;
            if (dp != null)
            {
                return dp.Name; 
            }
#endif 
 
            PropertyInfo propertyInfo = propertyMember as PropertyInfo;
            if (propertyInfo != null) 
            {
                return propertyInfo.Name;
            }
            else 
            {
                MethodInfo methodInfo = propertyMember as MethodInfo; 
                if (methodInfo != null) 
                {
                    return methodInfo.Name.Substring("Get".Length); 
                }
            }

            return null; 
        }
 
        ///  
        /// Given an object that is either a PropertyInfo, MethodInfo for the static
        /// setter, or DependencyProperty, return the type of the object that declares 
        /// or owns this property.
        /// 
        internal static Type GetDeclaringType(object propertyMember)
        { 
            Type validType = null;
            MemberInfo memInfo = propertyMember as MemberInfo; 
            if (memInfo != null) 
            {
                validType = memInfo.DeclaringType; 
            }
            else
            {
 
#if !PBTCOMPILER
                Debug.Assert( propertyMember is DependencyProperty); 
                validType = ((DependencyProperty)propertyMember).OwnerType; 
#endif
            } 

            return validType;
        }
#endregion Properties 

#region Types 
 
#if !PBTCOMPILER
        ///  
        ///  Return the type that corresponds to typeName, given that the type is
        ///  located as a subelement or property on the passed element.
        /// 
        ///  
        ///   The full xaml name of a type, including an xml namespace prefix, if needed.
        ///   The name is of the form prefix:typename, such as MyNs:MyNewButton 
        ///  
        /// 
        ///   A DependencyObject that is logical parent for the type to be resolved.  This 
        ///   is required because it is this element (or its ancestors) that contains
        ///   namespace mapping data that is needed to resolve the typeName.
        /// 
        ///  
        ///  The resolved clr type.  Null if not found
        ///  
        internal static Type GetTypeFromName(string typeName, DependencyObject element) 
        {
            if (element == null) 
            {
                throw new ArgumentNullException( "element" );
            }
            if (typeName == null) 
            {
                throw new ArgumentNullException( "typeName" ); 
            } 

            // Now map the prefix to an xml namespace uri 
            int colonIndex = typeName.IndexOf(':');
            string prefix = string.Empty;
            if (colonIndex > 0)
            { 
                prefix = typeName.Substring(0, colonIndex);
                typeName = typeName.Substring(colonIndex+1, typeName.Length-colonIndex-1); 
            } 

            // First, get the xmlns dictionary to map prefixes to xml namespace uris 
            XmlnsDictionary prefixDictionary = element.GetValue(XmlAttributeProperties.XmlnsDictionaryProperty)
                                               as XmlnsDictionary;

            object xmlNamespaceObject = (prefixDictionary != null) ? prefixDictionary[prefix] : null; 

            // Then get the list of NamespaceMapEntry objects that maps the xml namespace uri to one 
            // or more clr namespace / assembly pairs.  This should be stored on the root element 
            // of the tree.
            Hashtable namespaceMaps = element.GetValue(XmlAttributeProperties.XmlNamespaceMapsProperty) 
                                               as Hashtable;

            NamespaceMapEntry[] namespaces = (namespaceMaps != null && xmlNamespaceObject != null) ? namespaceMaps[xmlNamespaceObject] as NamespaceMapEntry[] : null;
 
            if (namespaces == null)
            { 
                // 

 


                if (prefix == string.Empty)
                { 
                    List namespaceAssemblyPair = GetClrNamespacePairFromCache(XamlReaderHelper.DefaultNamespaceURI);
                    foreach (ClrNamespaceAssemblyPair usd in namespaceAssemblyPair) 
                    { 
                        if (usd.AssemblyName != null)
                        { 
                            Assembly assy = ReflectionHelper.LoadAssembly(usd.AssemblyName, null);
                            if (assy != null)
                            {
                                string fullTypeName = String.Format(TypeConverterHelper.InvariantEnglishUS, "{0}.{1}", usd.ClrNamespace, typeName); 
                                Type t = assy.GetType(fullTypeName);
                                if (t != null) 
                                    return t; 
                            }
                        } 
                    }
                }

                // Stopgap didn't work, so fail now. 
                return null;
            } 
 
            // Check all the clr namespace / assembly pairs to see if there is a type
            // that matches the passed short name.  Return it if found. 
            for (int i = 0; i < namespaces.Length; i++)
            {
                Assembly assy = namespaces[i].Assembly;
                if (assy != null) 
                {
                    string fullTypeName = String.Format(TypeConverterHelper.InvariantEnglishUS, "{0}.{1}", namespaces[i].ClrNamespace, typeName); 
                    Type t = assy.GetType(fullTypeName); 
                    if (t != null)
                    { 
                        return t;
                    }
                }
            } 

            // Didn't find a match, so return null. 
            return null; 

       } 
#endif

        // Given a qualified member Name, returns its declaring Type and its name as a string.
        internal Type GetTargetTypeAndMember(string valueParam, 
                                             ParserContext context,
                                             bool isTypeExpected, 
                                         out string memberName) 
        {
            string typeName = valueParam; 
            string prefix = String.Empty;
            int typeIndex = typeName.IndexOf(':');
            if (typeIndex >= 0)
            { 
                prefix = typeName.Substring(0, typeIndex);
                typeName = typeName.Substring(typeIndex + 1); 
            } 

            memberName = null; 
            Type targetType = null;

            typeIndex = typeName.LastIndexOf('.');
            if (typeIndex >= 0) 
            {
                memberName = typeName.Substring(typeIndex + 1); 
                typeName = typeName.Substring(0, typeIndex); 
                string namespaceUri = context.XmlnsDictionary[prefix];
                TypeAndSerializer tas = GetTypeOnly(namespaceUri, typeName); 
                if (tas != null)
                {
                    targetType = tas.ObjectType;
                } 
                if (targetType == null)
                { 
                    ThrowException(SRID.ParserNoType, typeName); 
                }
            } 
            else if (!isTypeExpected && prefix.Length == 0)
            {
                // A Type may not be expected for e.g. for TemplateBinding param
                // values. In this case there must also not be a prefix. If there 
                // is one it will just point to a namespace and not a Type.
                memberName = typeName; 
            } 
            else
            { 
                // A type was expected but we didn't find one. So throw.
                ThrowException(SRID.ParserBadMemberReference, valueParam);
            }
 

            return targetType; 
        } 

        // Given a qualified member Name, returns its declaring Type and its name as a string. 
        internal Type GetDependencyPropertyOwnerAndName(string memberValue,
                                                        ParserContext context,
                                                        Type defaultTargetType,
                                                    out string memberName) 
        {
            Type targetType = GetTargetTypeAndMember(memberValue, context, false, out memberName); 
            if (targetType == null) 
            {
                targetType = defaultTargetType; 
                if (targetType == null)
                {
                    // if there was also no default target type then throw.
                    ThrowException(SRID.ParserBadMemberReference, memberValue); 
                }
            } 
 
            Debug.Assert(memberName != null);
            string fieldName = memberName + "Property"; 
            MemberInfo memberInfo = GetStaticMemberInfo(targetType, fieldName, true);
            Debug.Assert(memberInfo != null);

            // Need to get the actual type that declares the DP in order to 
            // correctly find a possible hit in the KnownProperties table.
            if (memberInfo.DeclaringType != targetType) 
            { 
                targetType = memberInfo.DeclaringType;
            } 

            return targetType;
        }
 
        // Gets the PropertyInfo or FieldInfo of a member.
        internal MemberInfo GetStaticMemberInfo(Type targetType, string memberName, bool fieldInfoOnly) 
        { 
            Debug.Assert(targetType != null);
            // first try public members only. 
            MemberInfo mi = GetStaticMemberInfo(targetType, memberName, fieldInfoOnly, false);

#if PBTCOMPILER
            if (mi == null) 
            {
                // If not found, then try non-public members next. 
                mi = GetStaticMemberInfo(targetType, memberName, fieldInfoOnly, true); 
                if (mi != null)
                { 
                    // if found, check access levels to see if it should really be allowed.
                    bool isAllowed = false;
                    PropertyInfo pi = mi as PropertyInfo;
                    if (pi != null) 
                    {
                        isAllowed = IsAllowedPropertyGet(pi, false); 
                    } 
                    else
                    { 
                        isAllowed = IsAllowedField(mi as FieldInfo);
                    }

                    if (!isAllowed) 
                    {
                        ThrowException(SRID.ParserStaticMemberNotAllowed, memberName, targetType.Name); 
                    } 
                }
            } 
#endif
            if (mi == null)
            {
                ThrowException(SRID.ParserInvalidStaticMember, memberName, targetType.Name); 
            }
 
            return mi; 
        }
 
        private MemberInfo GetStaticMemberInfo(Type targetType, string memberName, bool fieldInfoOnly, bool tryInternal)
        {
            MemberInfo memberInfo = null;
            BindingFlags bf = BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.Static; 

            if (tryInternal) 
            { 
                bf |= BindingFlags.NonPublic;
            } 

            if (!fieldInfoOnly)
            {
                memberInfo = targetType.GetProperty(memberName, bf); 
            }
 
            if (memberInfo == null) 
            {
                memberInfo = targetType.GetField(memberName, bf); 
            }

            return memberInfo;
        } 

        ///  
        /// Get the Type that type corresponds to a localName in 
        /// the given namespace.  Note that localName can be of the form classname.typename,
        /// and can not include a namespace prefix. 
        /// 
        /// 
        /// Return the actual type and the serializer for that type as a
        /// TypeAndSerializer object from the cache.  Note that in this call 
        /// the Serializer information may not be present if a new TypeAndSerializer
        /// instance is created.  Be sure to check the IsSerializerTypeSet flag. 
        ///  
        internal TypeAndSerializer GetTypeOnly (
                string    xmlNamespace,     // xml namespace for the type 
                string    localName)        // local name of the type without any '.'
        {

            Debug.Assert(null != xmlNamespace,"null value passed for xmlNamespace"); 
            Debug.Assert(null != localName,"null value passed for localName");
 
            // check if object is in the Hash. 
            String hashString = xmlNamespace + ":" + localName;
 
            TypeAndSerializer typeAndSerializer =
                 _typeLookupFromXmlHashtable[hashString] as TypeAndSerializer;

            if (null == typeAndSerializer) 
            {
                if (!_typeLookupFromXmlHashtable.Contains(hashString)) 
                { 
                    typeAndSerializer = CreateTypeAndSerializer(xmlNamespace, localName);
                    _typeLookupFromXmlHashtable[hashString] = typeAndSerializer; 
                }
            }

            return typeAndSerializer; 
        }
 
        ///  
        /// Get the Type and serializer for that type corresponding to a localName in
        /// the given namespace.  Note that localName can be of the form classname.typename, 
        /// and can not include a namespace prefix.
        /// 
        /// 
        /// Return the actual type and the serializer for that type as a 
        /// TypeAndSerializer object from the cache.  If there is no
        /// serializer defined, as is the case for clr objects, then null is set 
        /// for the SerializerType in the returned TypeAndSerializer. Also if this type is 
        /// associated with a property we will check for serializer attributes on the property first.
        /// If no matching attribute is found for the property we resort to search for the attribute on the given type. 
        /// 
        internal TypeAndSerializer GetTypeAndSerializer (
                string    xmlNamespace,     // xml namespace for the type
                string    localName,        // local name of the type without any '.' 
                object    dpOrPiorMi)       // property associated with the type
        { 
 
            Debug.Assert(null != xmlNamespace,"null value passed for xmlNamespace");
            Debug.Assert(null != localName,"null value passed for localName"); 

            // check if object is in the Hash.
            String hashString = xmlNamespace + ":" + localName;
 
            TypeAndSerializer typeAndSerializer =
                _typeLookupFromXmlHashtable[hashString] as TypeAndSerializer; 
 
            if (null == typeAndSerializer)
            { 
                if (!_typeLookupFromXmlHashtable.Contains(hashString))
                {
                    typeAndSerializer = CreateTypeAndSerializer(xmlNamespace, localName);
                    _typeLookupFromXmlHashtable[hashString] = typeAndSerializer; 
                }
            } 
 
            // If we've found a TypeAndSerializer, check whether we have reflected for the
            // serializer information yet.  If not, then do it now. 
            if (typeAndSerializer != null && !typeAndSerializer.IsSerializerTypeSet)
            {
                // Check for SerializerAttribute on the type. The serializer for the type is evaluated
                // the very first time we create a new data strcuture for the given type. 
                typeAndSerializer.SerializerType = GetXamlSerializerForType(typeAndSerializer.ObjectType);
                typeAndSerializer.IsSerializerTypeSet = true; 
            } 

            return typeAndSerializer; 
        }

#if PBTCOMPILER
        private static bool IsFriendAssembly(Assembly assembly) 
        {
            // WinFx assemblies can never be friends of compiled assemblies, so just bail out. 
            if (assembly == XamlTypeMapper.AssemblyPF || 
                assembly == XamlTypeMapper.AssemblyPC ||
                assembly == XamlTypeMapper.AssemblyWB) 
            {
                return false;
            }
 
            return ReflectionHelper.IsFriendAssembly(assembly);
        } 
 
        private static bool IsInternalAllowedOnType(Type type)
        { 
            bool isInternalAllowed = ReflectionHelper.LocalAssemblyName == type.Assembly.GetName().Name ||
                                     IsFriendAssembly(type.Assembly);
            _hasInternals = _hasInternals || isInternalAllowed;
            return isInternalAllowed; 
        }
 
        private static bool IsInternalAllowedOnType(NamespaceMapEntry namespaceMap) 
        {
            bool isInternalAllowed = namespaceMap.LocalAssembly || IsFriendAssembly(namespaceMap.Assembly); 
            _hasInternals = _hasInternals || isInternalAllowed;
            return isInternalAllowed;
        }
 
        internal static bool HasInternals
        { 
            get { return _hasInternals; } 
            set { _hasInternals = value; }
        } 

        internal static bool HasLocalReference
        {
            get 
            {
                return _hasLocalReference; 
            } 
        }
#endif 

        /// 
        /// Create a TypeAndSerializer object for the passed data, if a valid Type
        /// is found. 
        /// 
        private TypeAndSerializer CreateTypeAndSerializer( 
                string    xmlNamespace,     // xml namespace for the type 
                string    localName)        // local name of the type without any '.'
        { 
            TypeAndSerializer typeAndSerializer = null;
            NamespaceMapEntry[] namespaceMaps = GetNamespaceMapEntries(xmlNamespace);

            if (namespaceMaps != null) 
            {
                // We'll do a first pass with only known types 
                // and then do a second pass with full reflection 
                bool knownTypesOnly = true;
                for (int count = 0; count < namespaceMaps.Length;) 
                {
                    NamespaceMapEntry namespaceMap = namespaceMaps[count];
                    if (null != namespaceMap)
                    { 
                        Type objectType = GetObjectType(namespaceMap, localName, knownTypesOnly);
                        if (null != objectType) 
                        { 
                            // A non-public type is never allowable, except for internal types
                            // in local or friend assemblies, so catch it here. 
                            if (!ReflectionHelper.IsPublicType(objectType))
                            {
#if PBTCOMPILER
                                // Don't allow internal known types in case we have any. 
                                if (knownTypesOnly ||
                                    !ReflectionHelper.IsInternalType(objectType) || 
                                    !IsInternalAllowedOnType(namespaceMap)) 
#else
                                // Give Full Trust callers a chance to resolve legitimate internal types. 
                                // This can be used by tools like designers and localizers running in FT.
                                if (!IsInternalTypeAllowedInFullTrust(objectType))
#endif
                                { 
                                    ThrowException(SRID.ParserPublicType, objectType.Name);
                                } 
                            } 
                            // Create new data structure to store information for the current type
                            typeAndSerializer = new TypeAndSerializer(); 
                            typeAndSerializer.ObjectType = objectType;

                            break;
                        } 
                    }
 
                    count++; 
                    if (knownTypesOnly && (count == namespaceMaps.Length))
                    { 
                        // Reset for second pass
                        knownTypesOnly = false;
                        count = 0;
                    } 
                }
            } 
            return typeAndSerializer; 
        }
 

        /// 
        /// Return the Type that corresponds to a localName within a given clr namespace
        /// in a given assembly 
        /// 
        /// Specifies the CLR namespace and Assembly to look in 
        /// The name of the type 
        /// Search only known types
        /// Type of object that corresponds to localName 
        private Type GetObjectType(
            NamespaceMapEntry namespaceMap,
            string            localName,
            bool              knownTypesOnly) 
        {
            Debug.Assert(namespaceMap.ClrNamespace != null,"Null CLR Namespace"); 
            Debug.Assert(localName != null,"Null localName"); 

            Type type = null; 

            // Construct the full type name by concatenating the clr namespace and the local name

            if (knownTypesOnly) 
            {
                short typeID = BamlMapTable.GetKnownTypeIdFromName(namespaceMap.AssemblyName, namespaceMap.ClrNamespace, localName); 
                if (typeID != 0) 
                {
                    type = BamlMapTable.GetKnownTypeFromId(typeID); 
                }
            }
            else
            { 
               Assembly assembly ;
#if PBTCOMPILER 
                try 
                {
#endif 
                    // This may not work if the assembly is not present at compile time, so allow for that.
                    // At runtime it had better be there, so don't ignore it.
                    assembly = namespaceMap.Assembly;
#if PBTCOMPILER 
                }
                catch (FileNotFoundException) 
                { 
                    assembly = null;
                } 
#endif

                if (null != assembly)
                { 
                    // Type loads may fail if all the prerequisite assemblies haven't been loaded
                    // yet.  In this case, try one more time after loaded all assemblies that the 
                    // compiler may have told the XamlTypeMapper about. 
                    string fullTypeName = namespaceMap.ClrNamespace + "." + localName;
                    try 
                    {
                        type = assembly.GetType(fullTypeName);

                    } 
                    catch (Exception e)
                    { 
                        if (CriticalExceptions.IsCriticalException(e)) 
                        {
                           throw; 
                        }
                        else
                        {
                            if (LoadReferenceAssemblies()) 
                            {
                                try 
                                { 
                                    type = assembly.GetType(fullTypeName);
                                } 
                                catch (ArgumentException)
                                {
                                    // A null type is allowable, and the caller will catch it
                                    type = null; 
                                }
                            } 
                        } 
                    }
                } 
            }

            return type;
        } 

        internal int GetCustomBamlSerializerIdForType(Type objectType) 
        { 
            // support for xaml -> custom binary and custom binary -> object.
            if (objectType == KnownTypes.Types[(int)KnownElements.Brush]) 
            {
                return (int)KnownElements.XamlBrushSerializer;
            }
            else if (objectType == KnownTypes.Types[(int)KnownElements.Geometry] || 
                     objectType == KnownTypes.Types[(int)KnownElements.StreamGeometry])
            { 
                // 
                // The only type of geometry that can be serialized to a string is
                // a StreamGeometry, so if objectType is Geometry and we're getting here 
                // then the attribute must in fact be a StreamGeometry.
                //
                return (int)KnownElements.XamlPathDataSerializer;
            } 
            else if (objectType == KnownTypes.Types[(int)KnownElements.Point3DCollection])
            { 
                return (int)KnownElements.XamlPoint3DCollectionSerializer; 
            }
            else if (objectType == KnownTypes.Types[(int)KnownElements.Vector3DCollection]) 
            {
                return (int)KnownElements.XamlVector3DCollectionSerializer;
            }
            else if (objectType == KnownTypes.Types[(int)KnownElements.PointCollection]) 
            {
                return (int)KnownElements.XamlPointCollectionSerializer; 
            } 
            else if (objectType == KnownTypes.Types[(int)KnownElements.Int32Collection])
            { 
                return (int)KnownElements.XamlInt32CollectionSerializer;
            }

            return 0; 
        }
 
        ///  
        /// Sees if type has a Xaml serializer attribute that gives the
        /// type name of the serializer and figure out the type. 
        /// 
        internal Type GetXamlSerializerForType(Type objectType)
        {
            // support for xaml -> baml and baml -> objects 
            if (objectType == KnownTypes.Types[(int)KnownElements.Style])
            { 
                return typeof(XamlStyleSerializer); 
            }
            else if (KnownTypes.Types[(int)KnownElements.FrameworkTemplate].IsAssignableFrom(objectType)) 
            {
                return typeof(XamlTemplateSerializer);
            }
 
            return null;
        } 
 
#if !PBTCOMPILER
        internal static Type GetInternalTypeHelperTypeFromAssembly(ParserContext pc) 
        {
            Assembly a = pc.StreamCreatedAssembly;
            if (a == null)
            { 
                return null;
            } 
 
            Type ithType = a.GetType(GeneratedNamespace + "." + GeneratedInternalTypeHelperClassName);
            if (ithType == null) 
            {
                // if GITH is not found, try to see if a root namespace was implicitly added to it.
                // This would be the case for assemblies built with VB that had a RootNamespace
                // property specified in the project file. 
                RootNamespaceAttribute rnsa = (RootNamespaceAttribute)Attribute.GetCustomAttribute(a, typeof(RootNamespaceAttribute));
                if (rnsa != null) 
                { 
                    string rootNamespace = rnsa.Namespace;
                    ithType = a.GetType(rootNamespace + "." + GeneratedNamespace + "." + GeneratedInternalTypeHelperClassName); 
                }
            }

            return ithType; 
        }
 
        private static InternalTypeHelper GetInternalTypeHelperFromAssembly(ParserContext pc) 
        {
            InternalTypeHelper ith = null; 
            Type ithType = GetInternalTypeHelperTypeFromAssembly(pc);
            if (ithType != null)
            {
                ith = (InternalTypeHelper)Activator.CreateInstance(ithType); 
            }
            return ith; 
        } 

        ///  
        /// This function needs to demand reflection permission in order to create instances of
        /// allowed\accessible internal types. If permission is granted, the parser will directly
        /// use reflection to create the internal instance. If not, it will call a method on a
        /// generated class in the user's code context in order to attempt creating the internal 
        /// instance using the user app's security context.
        ///  
        internal static object CreateInternalInstance(ParserContext pc, Type type) 
        {
            object instance = null; 
            // if caller has member access reflection permission, use reflection directly
            if (SecurityHelper.CallerHasMemberAccessReflectionPermission())
            {
                instance = Activator.CreateInstance(type, 
                                                    BindingFlags.Public |
                                                    BindingFlags.NonPublic | 
                                                    BindingFlags.Instance | 
                                                    BindingFlags.CreateInstance,
                                                    null, 
                                                    null,
                                                    TypeConverterHelper.InvariantEnglishUS);
            }
            else 
            {
                // else this must be an accessible internal type in PT --- call the generated InternalTypeHelper 
                // in the caller's secuirty context. 

                // In this case pc.StreamCreatedAssembly is guaranteed to be the assembly from which the current 
                // stream being read was created from. So even if the internal type were not legitimate, the call
                // to create it via ith.CreateInstance would fail in PT.
                InternalTypeHelper ith = XamlTypeMapper.GetInternalTypeHelperFromAssembly(pc);
                if (ith != null) 
                {
                    instance = ith.CreateInstance(type, TypeConverterHelper.InvariantEnglishUS); 
                } 
            }
 
            return instance;
        }

        ///  
        /// This function needs to demand reflection permission in order to get an allowed\accessible
        /// internal property value on an allowed\accessible type. If permission is granted, the parser 
        /// will directly use reflection to get the property value. If not, it will call a method on a 
        /// generated class in the user's code context in order to attempt getting the internal property
        /// value using the user app's security context. 
        /// 
        internal static object GetInternalPropertyValue(ParserContext pc, object rootElement, PropertyInfo pi, object target)
        {
            object propValue = null; 
            bool isPublicProperty = false;
            bool allowProtected = (rootElement is IComponentConnector) && (rootElement == target); 
            bool isAllowedProperty = IsAllowedPropertyGet(pi, allowProtected, out isPublicProperty); 

            if (isAllowedProperty) 
            {
                // if public getter on internal type or caller has member access permission, use reflection directly
                if (isPublicProperty || SecurityHelper.CallerHasMemberAccessReflectionPermission())
                { 
                    propValue = pi.GetValue(target, BindingFlags.Default, null, null, TypeConverterHelper.InvariantEnglishUS);
                } 
                else 
                {
                    // else this must be an internal property getter on an accessible internal or public type --- call 
                    // the generated helper in caller's secuirty context.

                    // In this case pc.StreamCreatedAssembly is guaranteed to be the assembly from which the current stream
                    // being read was created from. So even if the internal property were not legitimate, the call 
                    // to access it via ith.GetPropertyValue would fail in PT.
                    InternalTypeHelper ith = GetInternalTypeHelperFromAssembly(pc); 
                    if (ith != null) 
                    {
                        propValue = ith.GetPropertyValue(pi, target, TypeConverterHelper.InvariantEnglishUS); 
                    }
                }
            }
 
            return propValue;
        } 
 
        /// 
        /// This function needs to demand reflection permission in order to set an allowed\accessible internal 
        /// property value on an allowed\accessible type. If permission is granted, the parser will directly use
        /// reflection to set the property value. If not, it will call a method on a generated class in the user's
        /// code context in order to attempt setting the internal property value using the user app's security context.
        ///  
        internal static bool SetInternalPropertyValue(ParserContext pc, object rootElement, PropertyInfo pi, object target, object value)
        { 
            bool isPublicProperty = false; 
            bool allowProtected = (rootElement is IComponentConnector) && (rootElement == target);
            bool isAllowedProperty = IsAllowedPropertySet(pi, allowProtected, out isPublicProperty); 

            if (isAllowedProperty)
            {
                // if public setter on internal type or caller has member access permission, use reflection directly 
                if (isPublicProperty || SecurityHelper.CallerHasMemberAccessReflectionPermission())
                { 
                    pi.SetValue(target, value, BindingFlags.Default, null, null, TypeConverterHelper.InvariantEnglishUS); 
                    return true;
                } 
                else
                {
                    // else this must be an internal property setter on an accessible internal or public type --- call
                    // the generated helper in caller's secuirty context. 

                    // In this case pc.StreamCreatedAssembly is guaranteed to be the assembly from which the current stream 
                    // being read was created from. So even if the internal property were not legitimate, the call 
                    // to set it via ith.SetPropertyValue would fail in PT.
                    InternalTypeHelper ith = GetInternalTypeHelperFromAssembly(pc); 
                    if (ith != null)
                    {
                        ith.SetPropertyValue(pi, target, value, TypeConverterHelper.InvariantEnglishUS);
                        return true; 
                    }
                } 
            } 

            return false; 
        }

        /// 
        /// This function needs to demand reflection permission in order to create an accessible delegate for a 
        /// non public event handler method. If permission is granted, the parser will directly use reflection
        /// to create the delegate. If not, it will call a method on a generated class in the user's code context 
        /// in order to attempt creating the delegate using the user app's security context. 
        /// 
        internal static Delegate CreateDelegate(ParserContext pc, Type delegateType, object target, string handler) 
        {
            Delegate d = null;
            bool isAllowedDelegateType = ReflectionHelper.IsPublicType(delegateType) || ReflectionHelper.IsInternalType(delegateType);
 
            if (isAllowedDelegateType)
            { 
                if (SecurityHelper.CallerHasMemberAccessReflectionPermission()) 
                {
                    d = Delegate.CreateDelegate(delegateType, target, handler); 
                }
                else
                {
                    // target is always the root generated element. Check to see if it is in the 
                    // same assembly as the one from which the currently processed stream was created,
                    // as an added precaution. 
                    if (target.GetType().Assembly == pc.StreamCreatedAssembly) 
                    {
                        InternalTypeHelper ith = GetInternalTypeHelperFromAssembly(pc); 
                        if (ith != null)
                        {
                            d = ith.CreateDelegate(delegateType, target, handler);
                        } 
                    }
                } 
            } 

            return d; 
        }

        /// 
        /// This function needs to demand reflection permission in order to add a delegate handler for an 
        /// allowed\accessible internal event on an allowed\accessible type. If permission is granted, the
        /// parser will directly use reflection to add the event handler delegate. If not, it will call a 
        /// method on a generated class in the user's code context in order to attempt adding the internal 
        /// event handler delegate using the user app's security context.
        ///  
        internal static bool AddInternalEventHandler(ParserContext pc, object rootElement, EventInfo eventInfo, object target, Delegate handler)
        {
            bool isPublicEvent = false;
            bool allowProtected = rootElement == target; 
            bool isAllowedEvent = IsAllowedEvent(eventInfo, allowProtected, out isPublicEvent);
 
            if (isAllowedEvent) 
            {
                // if public event on internal type or caller has member access permission, use reflection directly 
                if (isPublicEvent || SecurityHelper.CallerHasMemberAccessReflectionPermission())
                {
                    eventInfo.AddEventHandler(target, handler);
                    return true; 
                }
                else 
                { 
                    // else this must be an internal event on an accessible internal or public type --- call
                    // the generated helper in caller's secuirty context. 

                    // In this case pc.StreamCreatedAssembly is guaranteed to be the assembly from which the current
                    // stream being read was created from. So even if the internal event ere not legitimate, the call
                    // to add a handler to it via ith.AddEventHandler would fail in PT. 
                    InternalTypeHelper ith = GetInternalTypeHelperFromAssembly(pc);
                    if (ith != null) 
                    { 
                        ith.AddEventHandler(eventInfo, target, handler);
                        return true; 
                    }
                }
            }
 
            return false;
        } 
#endif 

        // Return true if this is a locally compiled assembly 
        internal bool IsLocalAssembly(string namespaceUri)
        {
            bool localAssembly = false;
#if PBTCOMPILER 
            NamespaceMapEntry[] namespaceMaps = GetNamespaceMapEntries(namespaceUri);
            localAssembly = (namespaceMaps != null && namespaceMaps.Length == 1 && namespaceMaps[0].LocalAssembly); 
#endif 
            return localAssembly;
        } 

        /// 
        /// Given a string of the format MyNs:MyButton return the type that it refers to.  This uses
        /// the XmlnsDictionary in the passed parse context to resolve prefixes on the 
        /// type names
        ///  
        internal Type GetTypeFromBaseString( 
            string        typeString,
            ParserContext context, 
            bool          throwOnError)
        {
            string xmlns = string.Empty;
            Type keyObject = null; 
            // Check if the typeString is of the form xmlns:type.  If so, get
            // the appropriate mapped NamespaceURI.  If not, use the default URI 
            int colonIndex = typeString.IndexOf(':'); 
            if (colonIndex == -1)
            { 
                xmlns = context.XmlnsDictionary[string.Empty];
                if (xmlns == null)
                {
                    ThrowException(SRID.ParserUndeclaredNS, string.Empty); 
                }
            } 
            else 
            {
                string prefix = typeString.Substring(0, colonIndex); 
                xmlns = context.XmlnsDictionary[prefix];
                if (xmlns == null)
                {
                    ThrowException(SRID.ParserUndeclaredNS, prefix); 
                }
                else 
                { 
                    typeString = typeString.Substring(colonIndex + 1);
                } 
            }

#if !PBTCOMPILER
            // Optimize for SystemMetric types that are very frequently used. 
            if (string.CompareOrdinal(xmlns, XamlReaderHelper.DefaultNamespaceURI) == 0)
            { 
                switch (typeString) 
                {
                    case "SystemParameters": 
                        keyObject = typeof(SystemParameters);
                        break;

                    case "SystemColors": 
                        keyObject = typeof(SystemColors);
                        break; 
 
                    case "SystemFonts":
                        keyObject = typeof(SystemFonts); 
                        break;
                }
            }
#endif 
            if (keyObject == null)
            { 
                keyObject = GetType(xmlns, typeString); 
            }
 
            if (keyObject == null && throwOnError)
            {
                // if local type, then don't throw as it may be resolved in pass2.
                // it is upto the caller who has context about compilation passes 
                // to throw as appropriate in Pass2 if the type is still not found.
                if (!IsLocalAssembly(xmlns)) 
                { 
                    _lineNumber = context != null ? context.LineNumber : 0;
                    _linePosition = context != null ? context.LinePosition : 0; 

                    ThrowException(SRID.ParserResourceKeyType, typeString);
                }
            } 

            return keyObject; 
        } 

#if PBTCOMPILER 
        internal Type GetTypeArgsType(
            string typeString,
            ParserContext context,
            out string localTypeArgClassName, 
            out string localTypeArgNamespace)
        { 
            Type t = null; 
            localTypeArgClassName = string.Empty;
            localTypeArgNamespace = string.Empty; 

            // Check if the typeString is of the form xmlns:type.  If so, get
            // the appropriate mapped NamespaceURI.  If not, use the default URI
            int colonIndex = typeString.IndexOf(':'); 
            if (colonIndex == -1)
            { 
                string xmlns = context.XmlnsDictionary[string.Empty]; 
                if (xmlns == null)
                { 
                    ThrowException(SRID.ParserUndeclaredNS, string.Empty);
                }
                else
                { 
                    t = GetType(xmlns, typeString);
                } 
            } 
            else
            { 
                string prefix = typeString.Substring(0, colonIndex);
                string xmlns = context.XmlnsDictionary[prefix];
                if (xmlns == null)
                { 
                    ThrowException(SRID.ParserUndeclaredNS, prefix);
                } 
                else 
                {
                    NamespaceMapEntry[] namespaceMaps = GetNamespaceMapEntries(xmlns); 
                    typeString = typeString.Substring(colonIndex + 1);
                    bool isLocalArg = namespaceMaps != null &&
                                      namespaceMaps.Length == 1 &&
                                      namespaceMaps[0].LocalAssembly; 

                    if (isLocalArg) 
                    { 
                        localTypeArgNamespace = namespaceMaps[0].ClrNamespace;
                        localTypeArgClassName = typeString; 
                    }
                    else
                    {
                        t = GetType(xmlns, typeString); 
                    }
                } 
            } 

            return t; 
        }
#endif

        ///  
        /// Helper method given a type returns the Cached information for the type.  If there
        /// is no existing cached information for that type, a new cache object is created 
        /// and added to the cache. 
        /// 
        private TypeInformationCacheData GetCachedInformationForType(Type type) 
        {
            TypeInformationCacheData typeInformationCacheData;
            typeInformationCacheData = _typeInformationCache[type] as TypeInformationCacheData;
            if (null == typeInformationCacheData) 
            {
                typeInformationCacheData = new TypeInformationCacheData(type.BaseType); 
                typeInformationCacheData.ClrNamespace = type.Namespace; 

                _typeInformationCache[type] = typeInformationCacheData; 
            }

            return typeInformationCacheData;
        } 

#if !PBTCOMPILER 
 
        /// 
        /// Returns the type's BaseType. This is cached because the .net Type.BaseType() 
        /// call is expensive.
        /// 
        private Type GetCachedBaseType(Type t)
        { 
            TypeInformationCacheData typeInformation = GetCachedInformationForType(t);
 
            return typeInformation.BaseType; 
        }
 
        /***************************************************************************\
        *
        * XamlTypeMapper.ProcessNameString
        * 
        * Given a name in markup, extract and process the prefix if any.
        * 
        \***************************************************************************/ 

        internal static string ProcessNameString(ParserContext parserContext, ref string nameString) 
        {
            // For certain parts of the styling markup, a property is specified as an
            //  attribute value.  This may include the namespace specification.  Normally
            //  when we encounter this in an attribute the XML parser processes the name- 
            //  space for us.  But when it's the value we'll have to deal with it our-
            //  selves.  Look for the namespace specifier and extract it for namespace lookup. 
            //  "foons:BarClass.BazProp" -> "http://www.example.com" + "BarClass.BazProp" 

            // The colon is what we look for to determine if there's a namespace prefix specifier. 
            int nsIndex = nameString.IndexOf(':');
            string nsPrefix = string.Empty;
            if( nsIndex != -1 )
            { 
                // Found a namespace prefix separator, so create replacement propertyName.
                // String processing - split "foons" from "BarClass.BazProp" 
                nsPrefix = nameString.Substring (0, nsIndex); 
                nameString = nameString.Substring (nsIndex + 1);
            } 

            // Find the namespace, even if its the default one
            string namespaceURI = parserContext.XmlnsDictionary[nsPrefix];
            if (namespaceURI == null) 
            {
                parserContext.XamlTypeMapper.ThrowException(SRID.ParserPrefixNSProperty, nsPrefix, nameString); 
            } 

            return namespaceURI; 
        }

        /***************************************************************************\
        * 
        * XamlTypeMapper.ParsePropertyName
        * 
        * Given a property name, find the associated DependencyProperty and return it. 
        *
        \***************************************************************************/ 

        internal static DependencyProperty ParsePropertyName(
                ParserContext   parserContext,
                string          propertyName, 
            ref Type            ownerType)
        { 
            string namespaceURI = ProcessNameString(parserContext, ref propertyName); 

            DependencyProperty dp = parserContext.XamlTypeMapper.DependencyPropertyFromName( 
                                            propertyName,
                                            namespaceURI,
                                            ref ownerType);
 
            return dp;
        } 
 
        /****************************************************************************\
        * 
        * XamlTypeMapper.ParseEventName
        *
        * Given an event name, find the associated RoutedEvent and return it.
        * 
        \***************************************************************************/
 
        internal static RoutedEvent ParseEventName( 
            ParserContext   parserContext,
            string          eventName, 
            Type            ownerType)
        {
            string namespaceURI = ProcessNameString(parserContext, ref eventName);
 
            RoutedEvent Event = parserContext.XamlTypeMapper.GetRoutedEvent(
                ownerType, namespaceURI, eventName); 
 
            return Event;
        } 

#endif

        ///  
        /// Return an object of the passed type.
        ///  
        ///  
        /// If the type is a KnownElement (which it likely will be) it is faster
        /// to create it using the KnownTypes hardcoded constructors, so check that 
        /// first before using the Activator.CreateInstance fallback.
        /// 
        internal object CreateInstance(Type t)
        { 
            object o = null;
#if !PBTCOMPILER 
            short typeId = BamlMapTable.GetKnownTypeIdFromType(t); 
            if (typeId < 0)
            { 
                o = MapTable.CreateKnownTypeFromId(typeId);
            }
            else
            { 
#endif
                o = Activator.CreateInstance(t, 
                                             BindingFlags.Instance | BindingFlags.CreateInstance | BindingFlags.Public, 
                                             null,
                                             null, 
                                             TypeConverterHelper.InvariantEnglishUS);
#if !PBTCOMPILER
            }
#endif 
            return o;
        } 
 
#endregion Types
 
#region Namespaces

        // Return true if the passed namespace is known, meaning that it maps
        // to a set of assemblies and clr namespaces 
        internal bool IsXmlNamespaceKnown(
                string xmlNamespace, 
            out string newXmlNamespace) 
        {
            bool result; 

            // if the namespace is empty, then there's no need to do all the extra work associated with getting the
            // namespace map entries.  Just return false.
            if (String.IsNullOrEmpty(xmlNamespace)) 
            {
                result = false; 
                newXmlNamespace = null; 
            }
            else 
            {
                NamespaceMapEntry[] namespaceMaps = GetNamespaceMapEntries(xmlNamespace);
                if (_xmlnsCache == null)
                { 
#if PBTCOMPILER
                    Debug.Assert(false, "Should initialize cache prior to compiling"); 
#else 
                    _xmlnsCache = new XmlnsCache();
#endif 
                }
                newXmlNamespace = _xmlnsCache.GetNewXmlnamespace(xmlNamespace);

                // if the xmlNamespace has valid entries or is mapped to another namespace, then it is known. 
                result = (namespaceMaps != null && namespaceMaps.Length > 0) ||
                              !String.IsNullOrEmpty(newXmlNamespace); 
            } 

            return result; // return variable isn't needed, just makes debugging easier. 
        }


#if !PBTCOMPILER 

        // 
        // Pass xmlNamespace to AssemblyList mapping to xmlnsCache so that the xmlnsCache 
        // can take the assembly list to get the right xmlns->clrns mapping later.
        // 
        internal void SetUriToAssemblyNameMapping(string xmlNamespace, short[] assemblyIds)
        {
            //
            // If the xmlNamespace is for a mapping,  there is no need to ask for xmlnsCache 
            // to get xmlns->clrns mapping.
            // 
            if (xmlNamespace.StartsWith(XamlReaderHelper.MappingProtocol, StringComparison.Ordinal)) 
            {
                return; 
            }

            if (_xmlnsCache == null)
            { 
                _xmlnsCache = new XmlnsCache();
            } 
 
            string[] asmNameList = null;
 
            if (assemblyIds != null && assemblyIds.Length > 0)
            {
                asmNameList = new string[assemblyIds.Length];
 
                for (int i = 0; i < assemblyIds.Length; i++)
                { 
                    BamlAssemblyInfoRecord assemblyInfo = MapTable.GetAssemblyInfoFromId(assemblyIds[i]); 
                    asmNameList[i] = assemblyInfo.AssemblyFullName;
                } 
            }

            _xmlnsCache.SetUriToAssemblyNameMapping(xmlNamespace, asmNameList);
        } 

 
#endif 

        /// 
        /// Returns a NamespaceMapEntry array given a xmlNamespace.  Each
        /// NamespaceMapEntry contains information the XamlTypeMapper uses for Mapping between an xml
        /// XmlNamespace and what Assembly, Namespace to look in.
        /// 
        ///
        /// The xmlNamespace for the Map 
        /// 
        ///
        /// Returns an Array of NamespaceMapEntry 
        ///
        internal NamespaceMapEntry[] GetNamespaceMapEntries(string xmlNamespace)
        {
            NamespaceMapEntry[] namespaceMaps = null; 

            // check out hash and if already have resolved the Uri 
            // don't resolve again. 
            namespaceMaps = _namespaceMapHashList[xmlNamespace] as NamespaceMapEntry[];
 
            if (null == namespaceMaps)
            {
                ArrayList namespaceMapArray = new ArrayList(6);
 
                // this is the first time the XmlNamespace has been requested
                // add items from the namespaceMap and then walk the assembly 
                // list to find matching items. 

                if (null != _namespaceMaps) 
                {
                    // need to find out the total number of entries by asking each hash
                    // review, may be better to sort these firt time through
                    // assumption here that the namespaceMap entries are small. 
                    for (int i = 0; i < _namespaceMaps.Length; i++)
                    { 
                        NamespaceMapEntry namespaceMap = _namespaceMaps[i]; 

                        if (namespaceMap.XmlNamespace == xmlNamespace) 
                        {
                            namespaceMapArray.Add(namespaceMap);
                        }
                    } 
                }
 
 
                List namespaceAssemblyPair;
                // Check for Processing instructions for mapping.  If that fails, 
                // check for Xmlns definition files.
                if (PITable.Contains(xmlNamespace))
                {
                    namespaceAssemblyPair = new List(1); 
                    namespaceAssemblyPair.Add((ClrNamespaceAssemblyPair)PITable[xmlNamespace]);
                } 
                else 
                {
                    namespaceAssemblyPair = GetClrNamespacePairFromCache(xmlNamespace); 
                }

                // now walk through any using statements we got and add them
                if (null != namespaceAssemblyPair) 
                {
 
                    for (int j = 0; j < namespaceAssemblyPair.Count; j++) 
                    {
                        ClrNamespaceAssemblyPair mapping = namespaceAssemblyPair[j]; 
                        string          usingAssemblyName = null;
                        string          path =  AssemblyPathFor(mapping.AssemblyName);

                        // using could either have an assembly or not, if it does 
                        // have an assembly just need to add this one entry, if
                        // no assembly map in the referenced assemblies. 
 
                        if (
#if PBTCOMPILER 
                            mapping.LocalAssembly ||
#endif
                            (!(String.IsNullOrEmpty(mapping.AssemblyName)) && !(String.IsNullOrEmpty(mapping.ClrNamespace))) )
                        { 
                            usingAssemblyName = mapping.AssemblyName;
                            NamespaceMapEntry nsMap = new NamespaceMapEntry(xmlNamespace, 
                                usingAssemblyName,mapping.ClrNamespace,path); 

#if PBTCOMPILER 
                            nsMap.LocalAssembly = mapping.LocalAssembly;
                            // if xaml has local components, then it could have internals
                            // but there is no way to determine this until pass2. But we
                            // need to set this here in order to generate the InternalTypeHelper 
                            // in pass1.
                            if (nsMap.LocalAssembly) 
                            { 
                                _hasLocalReference = true;
                            } 
#endif

                            namespaceMapArray.Add(nsMap);
                        } 

                        if (!String.IsNullOrEmpty(mapping.ClrNamespace)) 
                        { 
                            // Also add in any assembly from the AssemblyNames collection
                            for (int k = 0; k < _assemblyNames.Length; k++) 
                            {
                                if (usingAssemblyName == null)
                                {
                                    namespaceMapArray.Add(new NamespaceMapEntry(xmlNamespace, 
                                                      _assemblyNames[k],
                                                      mapping.ClrNamespace, 
                                                      path)); 
                                }
                                else 
                                {
                                    // If we have a using Assembly, then only add assemblies from
                                    // AssemblyNames that match the using Assembly.
                                    int charIndex = _assemblyNames[k].LastIndexOf('\\'); 
                                    if (charIndex > 0 &&
                                        _assemblyNames[k].Substring(charIndex + 1) == usingAssemblyName) 
                                    { 
                                        namespaceMapArray.Add(new NamespaceMapEntry(xmlNamespace,
                                                        _assemblyNames[k], 
                                                        mapping.ClrNamespace,
                                                        path));
                                    }
                                } 
                            }
                        } 
                    } 
                }
 
                // convert to a namespaceMap
                namespaceMaps = (NamespaceMapEntry[]) namespaceMapArray.ToArray(typeof(NamespaceMapEntry));

                // add to hash even if not items so we don't do this work again. 
                if (null != namespaceMaps)
                { 
                    _namespaceMapHashList.Add(xmlNamespace,namespaceMaps); 
                }
            } 

            return namespaceMaps;
        }
 

#if PBTCOMPILER 
 
        /// 
        /// Invalide the namespace mapping cache associated with a namespace. This should be done 
        /// when the PITable has been changed and the mapping cache might have been built for the
        /// namespace already.
        /// 
        /// The namespace to for whose cache to invalidate 
        internal void InvalidateMappingCache(string xmlNamespace)
        { 
            _namespaceMapHashList.Remove(xmlNamespace); 
        }
 
        /// 
        /// Set up the XmlnsCache use for resolving namespaces to use only the assembly path
        /// table that has been built up by the XamlTypeMapper.
        ///  
        internal void InitializeReferenceXmlnsCache()
        { 
            _xmlnsCache = new XmlnsCache(_assemblyPathTable); 
        }
 
#else
        // Get the xml namespace from the _piReverseTable that corresponds to the
        // passed type full name and assembly name
        internal string GetXmlNamespace( 
            string  clrNamespaceFullName,
            string  assemblyFullName) 
        { 
            string upperAssemblyName = assemblyFullName.ToUpper(
                                              TypeConverterHelper.InvariantEnglishUS); 

            String fullName = clrNamespaceFullName + "#" + upperAssemblyName;

            String ret; 

            if (_piReverseTable.TryGetValue(fullName, out ret) && ret != null) 
            { 
                return ret;
            } 
            else
            {
               return string.Empty;
            } 
        }
 
        ///  
        /// Given a Type returns it's .net Namespace. This is cached because each call
        /// to .urtNamspace allocates a string. 
        /// 
        private string GetCachedNamespace(Type t)
        {
            TypeInformationCacheData typeInformation = GetCachedInformationForType(t); 

            return typeInformation.ClrNamespace; 
        } 
#endif
 
        /// 
        /// Check an Xml namespace URI and loads the associated Clr namespaces and assemblies
        /// into ClrNamespaceAssemblyPair structures.
        ///  Throws an exception if no valid namespaces are found. 
        /// 
        /// Xml namespace that maps to one or more Clr namespace 
        /// and assembly pairs 
        /// array of ClrNamespaceAssemblyPair structures
        internal static List GetClrNamespacePairFromCache( 
                string namespaceUri)
        {

            List mappingArray = null; 

            // 
 

 
            if (_xmlnsCache == null)
            {
#if PBTCOMPILER
                Debug.Assert(false, "Should initialize cache prior to compiling"); 
#else
                _xmlnsCache = new XmlnsCache(); 
#endif 
            }
 
            mappingArray = _xmlnsCache.GetMappingArray(namespaceUri);

            return mappingArray;
        } 

#endregion Namespaces 
 
#region TypeConverters
 
        // Returns the Type of the TypeConverter for the given type.
        // Returns null if not found.
        internal Type GetTypeConverterType(Type type)
        { 
            Debug.Assert(null != type, "Null passed for type to GetTypeConverterType");
            TypeInformationCacheData typeData = GetCachedInformationForType(type) as TypeInformationCacheData; 
            Type converterType = null; 

            if (null != typeData.TypeConverterType) 
            {
                converterType = typeData.TypeConverterType;
                return converterType;
            } 

            // Check for known TypeConverters first. These are always public. 
            converterType = MapTable.GetKnownConverterTypeFromType(type); 
            if (converterType == null)
            { 
                // If not found, next try looking for the TypeConverter for the type using reflection.
                converterType = TypeConverterHelper.GetConverterType(type);
                if (converterType == null)
                { 
                    converterType = TypeConverterHelper.GetCoreConverterTypeFromCustomType(type);
                } 
            } 

            typeData.TypeConverterType = converterType; 
            return converterType;
        }

#if !PBTCOMPILER 
        // Returns the TypeConverter for the given type
        // Throws a XamlParseException if no TypeConverter is found. 
        internal TypeConverter GetTypeConverter(Type type) 
        {
            Debug.Assert(null != type, "Null passed for type to GetTypeConverter"); 

            TypeInformationCacheData typeData = GetCachedInformationForType(type) as TypeInformationCacheData;
            TypeConverter typeConverter = null;
 
            // if the TypeConverter for this type was ever successfully
            // queried before it should have a non-null value. 
            if (null != typeData.Converter) 
            {
                typeConverter = typeData.Converter; 
                return typeConverter;
            }

            // Check for known TypeConverters first. These are always public. 
            typeConverter = MapTable.GetKnownConverterFromType(type);
            if (typeConverter == null) 
            { 
                // If not found, next try looking for the TypeConverter for the type using reflection.
                Type converterType = TypeConverterHelper.GetConverterType(type); 
                if (converterType == null)
                {
                    typeConverter = TypeConverterHelper.GetCoreConverterFromCustomType(type);
                } 
                else
                { 
                    typeConverter = CreateInstance(converterType) as TypeConverter; 
                }
            } 

            typeData.Converter = typeConverter;

            if (null == typeConverter) 
            {
                ThrowException(SRID.ParserNoTypeConv, type.Name); 
            } 

            return typeConverter; 
        }
#endif

        // Returns the Type of the TypeConverter applied to the given property itself. 
        // Returns null if not found.
        internal Type GetPropertyConverterType(Type propType, object dpOrPiOrMi) 
        { 
            Debug.Assert(null != propType, "Null passed for propType to GetPropertyConverterType");
            Type converterType = null; 

            // If the current value being parsed is a property value then we must look
            // if there is special TypeConverter specified as attribute for this property
            if (null != dpOrPiOrMi) 
            {
#if PBTCOMPILER 
                TypeInformationCacheData typeData = GetCachedInformationForType(propType) as TypeInformationCacheData; 
                object ret = typeData.PropertyConverters[dpOrPiOrMi];
                if (null != ret) 
                {
                    converterType = (Type)ret;
                    return converterType;
                } 
                else
#endif 
                { 
                    // Get the memberInfo from the DP, PropertyInfo(CLR) or MethodInfo(Attached) for the property
                    MemberInfo memberInfo = TypeConverterHelper.GetMemberInfoForPropertyConverter(dpOrPiOrMi); 
                    if (memberInfo != null)
                    {
                        // If not found, next try looking for the TypeConverter on the property itself using reflection.
                        converterType = TypeConverterHelper.GetConverterType(memberInfo); 
                    }
                } 
 
#if PBTCOMPILER
                // Cache the per property TypeConverter type. This doesn't need to be cached at run-time 
                // since GetPropertyConverter will be used for getting the actual TypeConveretr instance.
                // This saves us the cost of a HashTable.
                typeData.SetPropertyConverter(dpOrPiOrMi, converterType);
#endif 
            }
 
            return converterType; 
        }
 
#if !PBTCOMPILER
        // Returns the TypeConverter applied to the given property iself.
        // If not found returns the TypeConverter applied to the given property's type.
        // Throws a XamlParseException if no TypeConverter is found. 
        internal TypeConverter GetPropertyConverter(Type propType, object dpOrPiOrMi)
        { 
            Debug.Assert(null != propType, "Null passed for propType to GetPropertyConverter"); 
            TypeConverter typeConverter = null;
 
            TypeInformationCacheData typeData = GetCachedInformationForType(propType) as TypeInformationCacheData;

            // If the current value being parsed is a property value then we must look
            // if there is special TypeConverter specified as attribute for this property 
            if (null != dpOrPiOrMi)
            { 
                object ret = typeData.PropertyConverters[dpOrPiOrMi]; 
                if (null != ret)
                { 
                    typeConverter = (TypeConverter)ret;
                    return typeConverter;
                }
 
                // Get the memberInfo from the DP, PropertyInfo(CLR) or MethodInfo(Attached) for the property
                MemberInfo memberInfo = TypeConverterHelper.GetMemberInfoForPropertyConverter(dpOrPiOrMi); 
                if (memberInfo != null) 
                {
                    // If not found, next try looking for the TypeConverter on the property itself using reflection. 
                    Type converterType = TypeConverterHelper.GetConverterType(memberInfo);
                    if (converterType != null)
                    {
                        // create an instance of the TypeConverter if found 
                        typeConverter = CreateInstance(converterType) as TypeConverter;
                    } 
                } 
            }
 
            // If no TypeConverter is found on the property itself, try to find it based on the property's type
            if (typeConverter == null)
            {
                typeConverter = GetTypeConverter(propType); 
            }
 
            // Cache the per property TypeConverter 
            if (dpOrPiOrMi != null)
                typeData.SetPropertyConverter(dpOrPiOrMi, typeConverter); 

            return typeConverter;
        }
#endif 

#endregion TypeConverters 
 
#region Resources
 
        /// 
        /// Given a string, return a key to be used in a dictionary relating to this string.
        /// If the string is a simple string, just return that.  If the string represents a
        /// Typeof declaration, then return the Type that maps to that string. 
        /// Note that this can return null if the key is not resolved.  It is up to the caller
        /// to throw the appropriate error message in that case. 
        ///  
        internal object GetDictionaryKey(string keyString, ParserContext context)
        { 
             if (keyString.Length > 0 &&
                 (Char.IsWhiteSpace(keyString[0]) ||
                  Char.IsWhiteSpace(keyString[keyString.Length-1])))
             { 
                keyString = keyString.Trim();
             } 
             return keyString; 
        }
 
#endregion Resources

#if !PBTCOMPILER
 
#region ConstructorInfos
 
        ///  
        /// Fetches the cached ConstructorInfos if there exists one or
        /// then creates a new one and caches it for later. 
        /// 
        internal ConstructorData GetConstructors(Type type)
        {
            // Create a cache if it does not already exist 
            if (_constructorInformationCache == null)
            { 
                _constructorInformationCache = new HybridDictionary(3); 
            }
 
            // Add an entry for the current type if it does not already exist
            if (!_constructorInformationCache.Contains(type))
            {
                _constructorInformationCache[type] = new ConstructorData(type.GetConstructors(BindingFlags.Public | BindingFlags.Instance)); 
            }
 
            // Return the cached value 
            return (ConstructorData)_constructorInformationCache[type];
        } 

        /// 
        /// Helper class that is used to store constructor information for a type
        ///  
        internal class ConstructorData
        { 
            #region Constructors 

            internal ConstructorData(ConstructorInfo[] constructors) 
            {
                _constructors = constructors;
            }
 
            #endregion Constructors
 
            #region Methods 

            ///  
            /// Fetches the cached ParameterInfos if there exists one or
            /// then creates a new one and caches it for later.
            /// 
            internal ParameterInfo[] GetParameters(int constructorIndex) 
            {
                // Create a parameters Cache if it does not already exist 
                if (_parameters == null) 
                {
                    Debug.Assert(_constructors != null, "This operation is legal only after the constructors have been fetched"); 
                    _parameters = new ParameterInfo[_constructors.Length][];
                }

                // Add an entry for the current constructor if it does not already exist 
                if (_parameters[constructorIndex] == null)
                { 
                    _parameters[constructorIndex] = _constructors[constructorIndex].GetParameters(); 
                }
 
                // Return the cached value
                return _parameters[constructorIndex];
            }
 
            #endregion Methods
 
            #region Properties 

            internal ConstructorInfo[] Constructors 
            {
                get { return _constructors; }
            }
 
            #endregion Properties
 
            #region Data 

            private ConstructorInfo[] _constructors; 
            private ParameterInfo[][] _parameters;

            #endregion Data
        } 

#endregion ConstructorInfos 
 
#endif
 
#region TrimSurroundingWhitespace

        /// 
        /// Returns the Cached TrimSurroundingWhitespace for the associated type 
        /// We cache this because the reflection lookup on the attribute
        /// is slow. 
        ///  
        /// type to return the TrimSurroundingWhitespaceAttribute for
        /// The TrimSurroundingWhitespace value for t 
        internal bool GetCachedTrimSurroundingWhitespace(Type t)
        {
            TypeInformationCacheData typeInformation = GetCachedInformationForType(t);
 
            // if first time asked for the layout Type get it.
            if (!typeInformation.TrimSurroundingWhitespaceSet) 
            { 
                typeInformation.TrimSurroundingWhitespace = GetTrimSurroundingWhitespace(t);
                typeInformation.TrimSurroundingWhitespaceSet = true; 
            }

            return typeInformation.TrimSurroundingWhitespace;
        } 

        ///  
        ///  Helper function for  use to find out the TrimSurroundingWhitespace 
        ///  associated with a Type.
        ///  
        private bool GetTrimSurroundingWhitespace(Type type)
        {
            Debug.Assert(null != type, "null value for type passed to GetWhitespace");
 
            // in retail return default.
            if (null != type) 
            { 
#if !PBTCOMPILER
                TrimSurroundingWhitespaceAttribute[] trimAttribute = 
                    type.GetCustomAttributes(typeof(TrimSurroundingWhitespaceAttribute),true )
                    as TrimSurroundingWhitespaceAttribute[];

                if (trimAttribute.Length > 0) 
                {
                    Debug.Assert(1 == trimAttribute.Length,"More than one TrimWhitespace Attribute"); 
                    return true; 
                }
#else 
                // Reflecting for attributes doesn't work on asmmeta files, so
                // we have to hard code known layout types here.  This is very
                // fragile, but we'll fix it in M8.2. - It's end of M11 already though...
                if (KnownTypes.Types[(int)KnownElements.LineBreak].IsAssignableFrom(type)) 
                {
                    // 
                    return true; 
                }
#endif 
            }
            return false;
        }
 
#endregion TrimSurroundingWhitespace
 
#region Exceptions 

        // 
        // ThrowException wrappers for 0-3 parameter SRIDs
        //

        private void ThrowException(string id) 
        {
            ThrowExceptionWithLine(SR.Get(id), null); 
        } 

        internal void ThrowException(string id, string parameter) 
        {
            ThrowExceptionWithLine(SR.Get(id, parameter), null);
        }
 
        private void ThrowException(string id, string parameter1, string parameter2)
        { 
            ThrowExceptionWithLine(SR.Get(id, parameter1, parameter2), null); 
        }
 
        private void ThrowException(string id, string parameter1, string parameter2, string parameter3)
        {
            ThrowExceptionWithLine(SR.Get(id, parameter1, parameter2, parameter3), null);
        } 

 
 
        //
        // ThrowException wrapper that just adds the line number & position. 
        //

        internal void ThrowExceptionWithLine(string message, Exception innerException)
        { 
            XamlParseException.ThrowException(message, innerException, _lineNumber, _linePosition);
        } 
 

#endregion Exceptions 

#region Properties

        ///  
        /// Hashtable where key is the xmlNamespace, and value is the
        /// ClrNamespaceAssemblyPair structure containing clrNamespace and assembly 
        ///  
        internal HybridDictionary PITable
        { 
            get { return _piTable; }
        }

 
        /// 
        /// This is the associated BamlMapTable that contains information about what is 
        /// in a baml stream.  The XamlTypeMapper uses the map table (if present) as a cache 
        /// to store some assembly, type and property information.  If it is not present
        /// then this information is not cached and must be retrieved for every request. 
        /// 
        internal BamlMapTable MapTable
        {
            get { return _mapTable; } 
            set { _mapTable = value; }
        } 
 
        /// 
        /// Line number used for error reporting 
        /// 
        internal int LineNumber
        {
            set { _lineNumber = value; } 
        }
 
        ///  
        /// Line position used for error reporting
        ///  
        internal int LinePosition
        {
            set { _linePosition = value; }
        } 

#if !PBTCOMPILER 
        ///  
        ///  Return the hashtable that is keyed by xml namespace uri and
        ///  has values that are collection of NamespaceMapEntry objects for that 
        ///  xml namespace.
        /// 
        internal Hashtable NamespaceMapHashList
        { 
            get { return _namespaceMapHashList; }
        } 
 
        internal System.Xaml.XamlSchemaContext SchemaContext
        { 
            get
            {
                if (_schemaContext == null)
                { 
                    _schemaContext = new XamlTypeMapperSchemaContext(this);
                } 
                return _schemaContext; 
            }
        } 
#else
        // true if the Type Mapper can allow protected attributes.
        // This will be the case for a markup sub-classed root element only.
        internal bool IsProtectedAttributeAllowed 
        {
            get { return _isProtectedAttributeAllowed; } 
            set { _isProtectedAttributeAllowed = value; } 
        }
 
        internal void ResetMapper()
        {
            _piTable.Clear();
            _piReverseTable.Clear(); 
            _lineNumber = 0;
            _linePosition = 0; 
            _isProtectedAttributeAllowed = false; 

            NamespaceMapEntry[] defaultNsMaps = _namespaceMapHashList[XamlReaderHelper.DefaultNamespaceURI] as NamespaceMapEntry[]; 
            NamespaceMapEntry[] definitionNsMaps = _namespaceMapHashList[XamlReaderHelper.DefinitionNamespaceURI] as NamespaceMapEntry[];
            NamespaceMapEntry[] definitionMetroNsMaps = _namespaceMapHashList[XamlReaderHelper.DefinitionMetroNamespaceURI] as NamespaceMapEntry[];

            _namespaceMapHashList.Clear(); 
            if (null != defaultNsMaps)
            { 
                _namespaceMapHashList.Add(XamlReaderHelper.DefaultNamespaceURI, defaultNsMaps); 
            }
            if (null != definitionNsMaps) 
            {
                _namespaceMapHashList.Add(XamlReaderHelper.DefinitionNamespaceURI, definitionNsMaps);
            }
            if (null != definitionMetroNsMaps) 
            {
                _namespaceMapHashList.Add(XamlReaderHelper.DefinitionMetroNamespaceURI, definitionMetroNsMaps); 
            } 
        }
#endif 
#endregion Properties

        #region Data
 
        // Class used for Type information data cache.
        internal class TypeInformationCacheData 
        { 
            /// 
            /// Create a new instance of the type cache.  Note that the type of this cached 
            /// data is not stored anywhere in this object.  The type that this object pertains
            /// to is stored as the key in the _typeInformationCache dictionary.
            /// 
            internal TypeInformationCacheData(Type baseType) 
            {
                _baseType = baseType; 
            } 

            ///  
            /// Urt Namespace for this type
            /// 
            internal string ClrNamespace
            { 
#if !PBTCOMPILER
                get { return _clrNamespace; } 
#endif 
                set { _clrNamespace = value; }
            } 

#if !PBTCOMPILER
            /// 
            /// The parent type in the inheritance hierarchy of this type.  This is 
            /// stored here since BaseType lookups take some time.
            ///  
            internal Type BaseType 
            {
                get { return _baseType; } 
            }

            /// 
            /// TypeConverter associted with this type, if there is one.  This is stored 
            /// here so that GetTypeConverter does not need to be called as often.
            ///  
            internal TypeConverter Converter 
            {
                get { return _typeConverter; } 
                set { _typeConverter = value; }
            }
#endif
            // The type of the TypeConverter 
            internal Type TypeConverterType
            { 
                get { return _typeConverterType; } 
                set { _typeConverterType = value; }
            } 

            /// 
            /// TrimSurroundingWhitespace value for this type.
            ///  
            internal bool TrimSurroundingWhitespace
            { 
                get { return _trimSurroundingWhitespace; } 
                set { _trimSurroundingWhitespace = value; }
            } 

            /// 
            /// Flag to indicate if we have cached the TrimSurroundingWhitespace
            ///  
            internal bool TrimSurroundingWhitespaceSet
            { 
                get { return _trimSurroundingWhitespaceSet; } 
                set { _trimSurroundingWhitespaceSet = value; }
            } 

            /// 
            /// Get the DependencyProperty from the Hashtable of PropertyAndType
            /// keyed by DependencyProperty name 
            /// 
            internal PropertyAndType GetPropertyAndType(string dpName) 
            { 
                if (_dpLookupHashtable == null)
                { 
                    _dpLookupHashtable = new Hashtable();
                    return null;
                }
 
                return _dpLookupHashtable[dpName] as PropertyAndType;
            } 
 

            ///  
            /// Set a new PropertyAndType in the DependencyProperty information Hashtable.
            /// 
            internal void SetPropertyAndType(
                string          dpName, 
                PropertyInfo    dpInfo,
                Type            ownerType, 
                bool            isInternal) 
            {
                Debug.Assert(_dpLookupHashtable != null, 
                    "GetPropertyAndType must always be called before SetPropertyAndType");

                // add the type taking a lock
                PropertyAndType pAndT = _dpLookupHashtable[dpName] as PropertyAndType; 
                if (pAndT == null)
                { 
                    _dpLookupHashtable[dpName] = new PropertyAndType(null, dpInfo, false, true, ownerType, isInternal); 
                }
                else 
                {
                    pAndT.PropInfo = dpInfo;
                    pAndT.PropInfoSet = true;
                    pAndT.IsInternal = isInternal; 
                }
            } 
 
            /// 
            /// TypeConverters based upon attributes on property 
            /// 
            internal HybridDictionary PropertyConverters
            {
                get 
                {
                    if (null == _propertyConverters) 
                    { 
                        _propertyConverters = new HybridDictionary();
                    } 

                    return _propertyConverters;
                }
            } 

            ///  
            /// Set a new PropertyConverter for the given property. 
            /// NOTE: This method takes a lock on the table. So to set
            /// values into the table you must use this method. 
            /// 
            internal void SetPropertyConverter(
                object dpOrPi,
#if !PBTCOMPILER 
                TypeConverter converter)
#else 
                Type converter) 
#endif
            { 
                _propertyConverters[dpOrPi] = converter;
            }

            // Private data members 
            string        _clrNamespace;
            Type          _baseType; 
            bool          _trimSurroundingWhitespace; 
            Hashtable     _dpLookupHashtable;  // Hashtable of PropertyAndType keyed by dp name
            HybridDictionary     _propertyConverters = new HybridDictionary(); // Dictionary of TypeConverters keyed on dpOrPi 
            bool          _trimSurroundingWhitespaceSet;
#if !PBTCOMPILER
            TypeConverter _typeConverter;
#endif 
            Type          _typeConverterType;
        } 
 
        // DP setter method, PropertyInfo and Type record held in _dpLookupHashtable
        internal class PropertyAndType 
        {
            public PropertyAndType (MethodInfo dpSetter,
                                    PropertyInfo dpInfo,
                                    bool setterSet, 
                                    bool propInfoSet,
                                    Type ot, 
                                    bool isInternal) 
            {
                Setter      = dpSetter; 
                PropInfo    = dpInfo;
                OwnerType   = ot;
                SetterSet   = setterSet;
                PropInfoSet = propInfoSet; 
                IsInternal  = isInternal;
            } 
 
            public PropertyInfo PropInfo;
            public MethodInfo   Setter; 
            public Type         OwnerType;
            public bool         PropInfoSet;
            public bool         SetterSet;
            public bool         IsInternal; 
        }
 
        // Constants that identify special types of string values 
        internal const string MarkupExtensionTypeString = "Type ";
        internal const string MarkupExtensionStaticString = "Static "; 
//        internal const string MarkupExtensionNullString = "Null";
        internal const string MarkupExtensionDynamicResourceString = "DynamicResource ";

        // If the case or name of the assembly name changes in the Framework build, 
        // then the following will have to change also.
        internal const string PresentationFrameworkDllName  = "PresentationFramework"; 
 
        // Namespace & classname of the generated helper class for accessing allowed internal types in PT.
        internal const string GeneratedNamespace = "XamlGeneratedNamespace"; 
        internal const string GeneratedInternalTypeHelperClassName = "GeneratedInternalTypeHelper";

#if !PBTCOMPILER
        internal const string MarkupExtensionTemplateBindingString = "TemplateBinding "; 
#else
        private static bool _hasInternals = false; 
        private static bool _hasLocalReference = false; 
        private bool _isProtectedAttributeAllowed = false;
        internal static Assembly AssemblyWB = null; 
        internal static Assembly AssemblyPC = null;
        internal static Assembly AssemblyPF = null;
#endif
        // Map table associated with this XamlTypeMapper.  This contains information 
        // about what is stored in BAML.  The XamlTypeMapper makes use of the caches in
        // the BamlMapTable to store some assembly, type and property information. 
        BamlMapTable _mapTable; 

        // Array of assembly names that can be used when resolving clr namespaces 
        string[] _assemblyNames;

        // array or namespace map entries such as `http:// mappings.
        NamespaceMapEntry[] _namespaceMaps; 

        // HashTable of cached type lookups and the serializers for that type.  These 
        // are always TypeAndSerializer objects 
        Hashtable _typeLookupFromXmlHashtable = new Hashtable();
 
        // Hash table of mappings between xmlNamespace and mappings
        Hashtable _namespaceMapHashList = new Hashtable();

        // Hashtable where the key is the fullTypeName + '#' + propertyName and the value 
        HybridDictionary _typeInformationCache = new HybridDictionary();
 
#if !PBTCOMPILER 
        // Hashtable where the key is the type and the value is the set of constructors for that type
        HybridDictionary _constructorInformationCache; 

        // A SchemaContext that respects the namespace mappings, PIs, and assembly paths
        // passed in to this TypeMapper
        private XamlTypeMapperSchemaContext _schemaContext; 
#endif
 
        // Hashtable where key is the xmlNamespace, and value is the 
        // ClrNamespaceAssemblyPair structure containing clrNamespace and assembly
        HybridDictionary _piTable =  new HybridDictionary(); 

        // Hashtable where key is the clrNamespace + "#" + assemblyName and the
        // value is the corresponding xmlNamespace.  This is used for fast lookups
        // of xmlnamespace if you know the assembly and clr namespace. 
        Dictionary _piReverseTable = new Dictionary();
 
        // Hashtable where key is the assembly's short name that has been uppercased, 
        // and the value is a path where that assembly can be loaded from.
        // Always lock on this object when writing to it 
        HybridDictionary _assemblyPathTable = new HybridDictionary();

        // true if referenced assemblies in the _assemblyPathTable have been loaded
        bool _referenceAssembliesLoaded = false; 

        // Line number and position in original Xaml file corresponding to the 
        // current BAML record. 
        int _lineNumber = 0;
        int _linePosition = 0; 

        // Cache of namespace and assemblies.
        private static XmlnsCache _xmlnsCache = null;
 
#endregion Data
 
#endregion Internal 
    }
 
    // Todo: Move to a separate file.

    // Type of object and type of Serializer for that type.  If this type
    // also contains an [XmlLang] property, this caches the property info also. 
    // These are contained in the _typeLookupFromXmlHashtable hastable
    internal class TypeAndSerializer 
    { 
        public TypeAndSerializer()
        { 
        }

        public Type ObjectType = null;
        public Type SerializerType = null; 
        public bool IsSerializerTypeSet = false;
        public PropertyInfo XmlLangProperty; 
    } 

    ///  
    /// Contains information the XamlTypeMapper uses for Mapping between an xml
    /// XmlNamespace and what Assembly, Namespace to look in.
    /// 
    [DebuggerDisplay("'{_xmlNamespace}'={_clrNamespace}:{_assemblyName}")] 
#if PBTCOMPILER
    internal class NamespaceMapEntry 
#else 
    public class NamespaceMapEntry
#endif 
    {

        #region Constructors
 
        ///
        /// NamespaceMapEntry default constructor 
        /// 
        public NamespaceMapEntry()
        { 
        }

        /// 
        /// Constructor 
        /// 
        /// The XML NamespaceURi 
        /// Assembly to use when resolving a Tag 
        /// Namespace within the assembly
        public NamespaceMapEntry(string xmlNamespace,string assemblyName,string clrNamespace) 
        {
            if (xmlNamespace == null)
                throw new ArgumentNullException("xmlNamespace");
 
            if (assemblyName == null)
                throw new ArgumentNullException("assemblyName"); 
 
            if (clrNamespace == null)
                throw new ArgumentNullException("clrNamespace"); 

            _xmlNamespace = xmlNamespace;
            _assemblyName = assemblyName;
            _clrNamespace = clrNamespace; 
        }
 
        ///  
        /// Constructor
        ///  
        /// The XML NamespaceURi
        /// Assembly to use when resolving a Tag
        /// Namespace within the assembly
        /// Path to use when loading assembly.  This may be null. 
         internal NamespaceMapEntry(
                string xmlNamespace, 
                string assemblyName, 
                string clrNamespace,
                string assemblyPath) : this(xmlNamespace, assemblyName, clrNamespace) 
        {
            _assemblyPath = assemblyPath;
        }
 
        #endregion Constructors
 
 
        #region Properties
 
        /// 
        /// Xml namespace specified in the constructor
        /// 
        public string XmlNamespace 
        {
            get { return _xmlNamespace; } 
            set 
            {
                if (value == null) 
                {
                    throw new ArgumentNullException("value");
                }
                if (_xmlNamespace == null) 
                {
                    _xmlNamespace = value; 
                } 
            }
        } 

        /// 
        /// AssemblyName specified in the constructor
        ///  
        public string AssemblyName
        { 
            get { return _assemblyName; } 
            set
            { 
                if (value == null)
                {
                    throw new ArgumentNullException("value");
                } 
                if (_assemblyName == null)
                { 
                    _assemblyName = value; 
                }
            } 
        }

        /// 
        /// ClrNamespace specified within the constructor 
        /// 
        public string ClrNamespace 
        { 
            get { return _clrNamespace; }
            set 
            {
                if (value == null)
                {
                    throw new ArgumentNullException("value"); 
                }
                if (_clrNamespace == null) 
                { 
                    _clrNamespace = value;
                } 
            }
        }

 
        #endregion Properties
 
        ///  
        /// returns instance of the assembly associate with this
        /// namespace map 
        /// 
        internal Assembly Assembly
        {
            get 
            {
                if (null == _assembly && _assemblyName.Length > 0) 
                { 
#if PBTCOMPILER
                    // NOTE: At compile time a local assembly can already be loaded if being 
                    // referenced by dehydrated assemblies and so we should attempt to return
                    // that.
                    if (_isLocalAssembly)
                    { 
                        string assemblyNameLookup = _assemblyName.ToUpper(CultureInfo.InvariantCulture);
 
                        // Check if the assembly has already been loaded. 
                        if (!ReflectionHelper.HasAlreadyReflectionOnlyLoaded(assemblyNameLookup))
                        { 
                            return null;
                        }
                    }
 
#endif
                    _assembly = ReflectionHelper.LoadAssembly(_assemblyName, _assemblyPath); 
                } 

                return _assembly; 
            }
        }

        ///  
        /// Get and set the path to use when loading the assembly.
        ///  
        internal string AssemblyPath 
        {
            get { return _assemblyPath; } 
            set { _assemblyPath = value; }
        }

#if PBTCOMPILER 
        internal bool LocalAssembly
        { 
            get { return _isLocalAssembly; } 
            set { _isLocalAssembly = value; }
        } 

        bool     _isLocalAssembly;
#endif
 
#region Data
 
        string   _xmlNamespace; 
        string   _assemblyName;
        string   _assemblyPath; 
        Assembly _assembly;
        string   _clrNamespace;

#endregion Data 

    } 
 
    // This is a convenience holder for all the possible IDs that Xaml understands which could
    // be on an object element. 
    internal class XamlObjectIds
    {
        public string Name = null;
        public string Uid = null; 
        public object Key = null;
    } 
 

#region XmlParserDefaults Class 

    // class for getting and setting mapping defaults.
    internal static class XmlParserDefaults
    { 

#region Methods 
 
        /// 
        ///  Instance of XamlTypeMapper to use if none is specified in the 
        ///  ParserContext. XamlTypeMapper returned is has its assembly and namespace
        ///  maps initialized to those set
        ///  via SetDefaultXmlMapping() or one built from our internal defaults.
        ///  
        internal static XamlTypeMapper DefaultMapper
        { 
            get 
            {
                return new XamlTypeMapper(GetDefaultAssemblyNames(),GetDefaultNamespaceMaps()); 
            }
        }

#endregion Methods 

#region Properties 
 
        /// 
        /// Returns an array of the DefaultAssemblyNames 
        /// 
        internal static string[] GetDefaultAssemblyNames()
        {
            return (string[])_defaultAssemblies.Clone(); 
        }
 
        ///  
        /// Returns array of the DefaultNamespaceMaps
        ///  
        internal static NamespaceMapEntry[] GetDefaultNamespaceMaps()
        {
            return (NamespaceMapEntry[])_defaultNamespaceMapTable.Clone();
        } 

#endregion Properties 
 
#region Data
 
        // array of our defaultAssemblies.
        private static readonly string[] _defaultAssemblies = {"WindowsBase", "PresentationCore", "PresentationFramework"};

        // array of namespaceMaps the map an xmlns namespaceURI 
        // to the assembly and urtNamespace to search in when resolving the xml
 
        private static readonly NamespaceMapEntry[] _defaultNamespaceMapTable = { }; 

#endregion Data 
    }
#endregion XmlParserDefaults Class

} 

 
 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
 
//----------------------------------------------------------------------------
//
// File: XamlTypeMapper.cs
// 
// Description:
//  Maps namespaceURI and LocalName to appropriate element, properties, and events. 
// 
//
// History: 
//    7/19/01:    rogerg        Created
//    5/28/03:    peterost      Ported to wcp
//    9/20/04:    peterost      cleanup interfaces and caches
// 
// Copyright (C) 2003 by Microsoft Corporation.  All rights reserved.
// 
//--------------------------------------------------------------------------- 

using System; 
using System.Xml;
using System.IO;
using System.Text;
using System.Collections; 
using System.Collections.Generic;
using System.Globalization; 
using System.ComponentModel; 
using System.Collections.Specialized;
using System.Diagnostics; 
using System.Reflection;
using MS.Utility;

#if !PBTCOMPILER 

using System.Windows; 
using System.Windows.Markup; 
using System.Windows.Resources;
using System.Windows.Threading; 
using SecurityHelper=MS.Internal.PresentationFramework.SecurityHelper;
using MS.Internal;  // CriticalExceptions

#else 

using System.Runtime.CompilerServices; 
 
#endif
 
// Disabling 1634 and 1691:
// In order to avoid generating warnings about unknown message numbers and
// unknown pragmas when compiling C# source code with the C# compiler,
// you need to disable warnings 1634 and 1691. (Presharp Documentation) 
#pragma warning disable 1634, 1691
 
#if PBTCOMPILER 
namespace MS.Internal.Markup
#else 
namespace System.Windows.Markup
#endif
{
 
    ///
    /// Handles mapping between XML NamepaceURI and .NET namespace types 
    /// 
#if PBTCOMPILER
    internal class XamlTypeMapper 
#else
    public partial class XamlTypeMapper
#endif
    { 
#region Public
 
#region Methods 

#if !PBTCOMPILER 
        /// 
        /// Constructor
        /// 
        /// Assemblies XamlTypeMapper should use when resolving XAML 
        public XamlTypeMapper(string[] assemblyNames)
        { 
            if(null == assemblyNames) 
            {
                throw new ArgumentNullException( "assemblyNames" ); 
            }

            _assemblyNames = assemblyNames;
            _namespaceMaps = null; 
        }
#endif 
 
        /// 
        /// Constructor 
        /// 
        /// Assemblies XamlTypeMapper should use when resolving XAML
        /// NamespaceMap the XamlTypeMapper should use when resolving XAML
        public XamlTypeMapper( 
            string[] assemblyNames,
            NamespaceMapEntry[] namespaceMaps) 
        { 
            if(null == assemblyNames)
            { 
                throw new ArgumentNullException( "assemblyNames" );
            }

            _assemblyNames = assemblyNames; 
            _namespaceMaps = namespaceMaps;
#if PBTCOMPILER 
            _hasInternals = false; 
            _hasLocalReference = false;
#endif 
        }

        /// 
        /// Helper to map an Xaml tag to a DotNet Type 
        /// 
        ///  
        /// Example: 
        ///     If the xml contained the tags 
        ///     you would call XamlTypeMapper.GetType("AvalonBase","Button"); 
        ///     
        ///     Note the XmlNamespace "AvalonBase" is the actual namespace value, not
        ///     the base: prefix.
        ///  
        /// NamespaceURI of tag
        /// localName of the Tag 
        /// Type for the object. If no type was found NULL is returned 
        public Type GetType(
            string xmlNamespace, 
            string localName)
        {
            if(null == xmlNamespace)
            { 
                throw new ArgumentNullException( "xmlNamespace" );
            } 
            if(null == localName) 
            {
                throw new ArgumentNullException( "localName" ); 
            }

            TypeAndSerializer typeAndSerializer =
                GetTypeOnly(xmlNamespace,localName); 

            return typeAndSerializer != null ? typeAndSerializer.ObjectType : null; 
        } 

#if !PBTCOMPILER 
        /// 
        ///  Programmatic counterpart to the  XAML PI.  For example, 
        ///    
        ///  
        /// 
        /// The "swc" argument in the mapping PI example. 
        ///  
        /// 
        /// The "System.Windows.ComponentModel" argument in the mapping PI example. 
        /// 
        /// 
        /// The "PresentationFramework" argument in the mapping PI example.
        ///  
        public void AddMappingProcessingInstruction(
            string  xmlNamespace, 
            string  clrNamespace, 
            string  assemblyName )
        { 
            if( null == xmlNamespace )
            {
                throw new ArgumentNullException("xmlNamespace");
            } 
            if( null == clrNamespace )
            { 
                throw new ArgumentNullException("clrNamespace"); 
            }
            if( null == assemblyName ) 
            {
                throw new ArgumentNullException("assemblyName");
            }
 
            // Parameter validation : Check for String.Empty as well?
 
            // Add mapping to the table keyed by xmlNamespace 
            ClrNamespaceAssemblyPair pair = new ClrNamespaceAssemblyPair(clrNamespace, assemblyName);
            PITable[xmlNamespace] = pair; 

            // Add mapping to the table keyed by assembly and clrnamespace
            string upperAssemblyName = assemblyName.ToUpper(
                                              TypeConverterHelper.InvariantEnglishUS); 
            String fullName = clrNamespace + "#" + upperAssemblyName;
 
            _piReverseTable[fullName] = xmlNamespace; 

            // Add mapping to the SchemaContext 
            if (_schemaContext != null)
            {
                _schemaContext.SetMappingProcessingInstruction(xmlNamespace, pair);
            } 
        }
#endif 
        ///  
        ///     This allows specifying a path to use when loading the named assembly.
        ///  
        /// 
        /// The short name of the assembly, with no extension or path specified
        /// 
        ///  
        /// The file path of the assembly
        ///  
        public void SetAssemblyPath( 
            string assemblyName,
            string assemblyPath) 
        {
            if( null == assemblyName )
            {
                throw new ArgumentNullException("assemblyName"); 
            }
            if( null == assemblyPath ) 
            { 
                throw new ArgumentNullException("assemblyPath");
            } 
            if (assemblyPath == string.Empty)
            {
                _lineNumber = 0;  // Public API, so we don't know the line number.
                ThrowException(SRID.ParserBadAssemblyPath); 
            }
            if (assemblyName == string.Empty) 
            { 
                _lineNumber = 0;  // Public API, so we don't know the line number.
                ThrowException(SRID.ParserBadAssemblyName); 
            }

            string asmName = assemblyName.ToUpper(CultureInfo.InvariantCulture);
            lock (_assemblyPathTable) 
            {
                _assemblyPathTable[asmName] = assemblyPath; 
            } 

#if PBTCOMPILER 
            PreLoadDefaultAssemblies(asmName, assemblyPath);
#else
            // Allow people to reset the path of previously loaded assemblies
            // so they can be loaded again.   The is the Dev build/load/build/load 
            // Designer scenario.  (Don't mess with GACed assemblies)
            Assembly assem = ReflectionHelper.GetAlreadyLoadedAssembly(asmName); 
            if (assem != null && !assem.GlobalAssemblyCache) 
            {
                ReflectionHelper.ResetCacheForAssembly(asmName); 
                // No way to reset SchemaContext at assembly granularity, so just reset the whole context
                if (_schemaContext != null)
                {
                    _schemaContext = null; 
                }
            } 
#endif 
        }
 
#endregion Methods

#region Properties
 
        /// 
        ///  Instance of XamlTypeMapper to use if none is specified in a 
        ///  ParserContext.  XamlTypeMapper returned is the internal default. 
        /// 
        public static XamlTypeMapper DefaultMapper 
        {
            get
            {
                return XmlParserDefaults.DefaultMapper; 
            }
        } 
 
#endregion Properties
 
#endregion Public

#region Internal
 
#region Initialization
 
#if !PBTCOMPILER 
        ///
        /// Initialize the XamlTypeMapper so that it is ready for a parse operation. 
        ///
        internal void Initialize()
        {
            _typeLookupFromXmlHashtable.Clear(); 
            _namespaceMapHashList.Clear();
            _piTable.Clear(); 
            _piReverseTable.Clear(); 
            lock (_assemblyPathTable)
            { 
                _assemblyPathTable.Clear();
            }
            _referenceAssembliesLoaded = false;
        } 
#endif
 
        // Return a new XamlTypeMapper that has the same instance variables as this instance, 
        // will all complex properties deep copied.
#if !PBTCOMPILER 
        internal XamlTypeMapper Clone()
        {
            XamlTypeMapper newMapper = new XamlTypeMapper(_assemblyNames.Clone() as string[]);
 
            newMapper._mapTable = _mapTable;
            newMapper._referenceAssembliesLoaded = _referenceAssembliesLoaded; 
            newMapper._lineNumber = _lineNumber; 
            newMapper._linePosition = _linePosition;
 
            newMapper._namespaceMaps = _namespaceMaps.Clone() as NamespaceMapEntry[];
            newMapper._typeLookupFromXmlHashtable = _typeLookupFromXmlHashtable.Clone() as Hashtable;
            newMapper._namespaceMapHashList = _namespaceMapHashList.Clone() as Hashtable;
            newMapper._typeInformationCache = CloneHybridDictionary(_typeInformationCache); 
            newMapper._piTable = CloneHybridDictionary(_piTable);
            newMapper._piReverseTable = CloneStringDictionary(_piReverseTable); 
            newMapper._assemblyPathTable = CloneHybridDictionary(_assemblyPathTable); 

            return newMapper; 
        }
#endif

#if !PBTCOMPILER 
        private HybridDictionary CloneHybridDictionary(HybridDictionary dict)
        { 
            HybridDictionary newDict = new HybridDictionary(dict.Count); 
            foreach ( DictionaryEntry de in dict )
            { 
                newDict.Add(de.Key, de.Value);
            }
            return newDict;
        } 
#endif
 
#if !PBTCOMPILER 
        private Dictionary CloneStringDictionary(Dictionary dict)
        { 
            Dictionary newDict = new Dictionary();
            foreach (KeyValuePair kvp in dict)
            {
                newDict.Add(kvp.Key, kvp.Value); 
            }
            return newDict; 
        } 
#endif
 
#endregion Initialization

#region Assemblies
 
        ///
        /// Returns the assembly path for the passed assembly.  If none, return null. 
        /// 
        internal string AssemblyPathFor(string assemblyName)
        { 
            string path = null;
            if (assemblyName != null)
            {
                // This method is used by SchemaContext, which needs to be thread-safe, so lock around it 
                lock (_assemblyPathTable)
                { 
                    path = _assemblyPathTable[assemblyName.ToUpper( 
                                            CultureInfo.InvariantCulture)] as string;
                } 
            }

#if PBTCOMPILER
 
            if (path == null)
            { 
                // If the assembly name contains full assembly name, we should use the short 
                // assembly name to search the assembly path cache table.
 
                int indexComma = assemblyName.IndexOf(",", StringComparison.Ordinal);

                if (indexComma > 0)
                { 
                    string assemblyShortName = assemblyName.Substring(0, indexComma).ToUpper(CultureInfo.InvariantCulture);
                    path = _assemblyPathTable[assemblyShortName] as String; 
                } 
            }
#endif 

            return path;
        }
 
        /// 
        /// Load assemblies that are in the referenced assembly list passed to the XamlTypeMapper 
        /// by the compiler.  Don't load known assemblies that should already be present, 
        /// since the references may not be the correct versions (see windows bugs 927372
        /// and 929395) 
        /// 
        private bool LoadReferenceAssemblies()
        {
            if (!_referenceAssembliesLoaded) 
            {
                _referenceAssembliesLoaded = true; 
                foreach (DictionaryEntry entry in _assemblyPathTable) 
                {
                    ReflectionHelper.LoadAssembly(entry.Key as String, entry.Value as String); 
                }
                return true;
            }
            else 
            {
                // Already loaded, so they don't need to be loaded again 
                return false; 
            }
        } 

#endregion Assemblies

#region AssemblyLoading 

#if  PBTCOMPILER 
 
        private void PreLoadDefaultAssemblies(string asmName, string asmPath)
        { 
            if (AssemblyWB == null && string.Compare(asmName, _assemblyNames[0], StringComparison.OrdinalIgnoreCase) == 0)
            {
                AssemblyWB = ReflectionHelper.LoadAssembly(asmName, asmPath);
            } 
            else if (AssemblyPC == null && string.Compare(asmName, _assemblyNames[1], StringComparison.OrdinalIgnoreCase) == 0)
            { 
                AssemblyPC = ReflectionHelper.LoadAssembly(asmName, asmPath); 
            }
            else if (AssemblyPF == null && string.Compare(asmName, _assemblyNames[2], StringComparison.OrdinalIgnoreCase) == 0) 
            {
                AssemblyPF = ReflectionHelper.LoadAssembly(asmName, asmPath);
            }
            else if (string.Compare(asmName, "SYSTEM.XML", StringComparison.OrdinalIgnoreCase) == 0) 
            {
                // make sure System.Xml is at least loaded as ReflectionOnly 
                ReflectionHelper.LoadAssembly(asmName, asmPath); 
            }
            else if (string.Compare(asmName, "SYSTEM", StringComparison.OrdinalIgnoreCase) == 0) 
            {
                // make sure System is at least loaded as ReflectionOnly
                ReflectionHelper.LoadAssembly(asmName, asmPath);
            } 
        }
 
        private ResolveEventHandler _areh = null; 

        internal void SetReflectionOnlyAssemblyResolver() 
        {
            // Register handler for prerequisite assemblies.  We may not necessarily load them
            // in the correct order, so the handler is responsbile for loading required assemblies.
            if (_areh == null) 
            {
                _areh = new ResolveEventHandler(OnReferencedAssemblyResolve); 
                AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += _areh; 
            }
        } 

        internal void ClearReflectionOnlyAssemblyResolver()
        {
            if (_areh != null) 
            {
                AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve -= _areh; 
                _areh = null; 
            }
        } 

        // This event handler is called when a ReflectionOnlyLoad can't succeed because of
        // a required assembly not being present.  This handler attempts to load that
        // assembly from the known place where the root assembly lives. 
        // NOTE:  It is assumed that all prerequisite assemblies are in the assembly path
        //        table passed to the TypeMapper via SetAssemblyPath(). 
        private Assembly OnReferencedAssemblyResolve( 
            object sender,
            ResolveEventArgs args) 
        {
            if (_assemblyPathTable != null && _assemblyPathTable.Count > 0)
            {
                AssemblyName assemblyName = new AssemblyName(args.Name); 
                string assemblyShortName = assemblyName.Name;
                assemblyShortName = assemblyShortName.ToUpper(CultureInfo.InvariantCulture); 
 
                Assembly asm = ReflectionHelper.GetAlreadyReflectionOnlyLoadedAssembly(assemblyShortName);
                if (asm != null) 
                {
                    if (assemblyName.Version != null)
                    {
                        AssemblyName cachedName = new AssemblyName(asm.FullName); 
                        if (!AssemblyName.ReferenceMatchesDefinition(assemblyName, cachedName))
                        { 
                            string request = assemblyName.ToString(); 
                            string found = cachedName.ToString();
                            throw new InvalidOperationException(SR.Get(SRID.ParserAssemblyLoadVersionMismatch, request, found)); 
                        }
                    }
                    return asm;
                } 
                else
                { 
                    string assemblyFullPath = _assemblyPathTable[args.Name] as String; 

                    if (!String.IsNullOrEmpty(assemblyFullPath) && File.Exists(assemblyFullPath)) 
                    {
                       return ReflectionHelper.LoadAssembly(args.Name, assemblyFullPath);
                    }
                } 
            }
 
            return ReflectionHelper.LoadAssembly(args.Name, null); 
        }
#endif 

#endregion AssemblyLoading

        #region Events 

#if !PBTCOMPILER 
 
        /// 
        /// Helper to map an Attribute to a RoutedEvent 
        /// 
        /// 
        ///    Example: 
        ///     If the xaml contained the tag  
        ///     you would call 
        /// 
        ///         Type owner = XamlTypeMapper.GetType("BaseXmlNs","Button");  
        ///         RoutedEvent = XamlTypeMapper.GetRoutedEvent(owner,"MyClick","BaseXmlNs");
        ///  
        /// Type of the owner
        /// Xml NamespaceURI of the attribute
        /// Local name of the attribute
        /// The RoutedEvent ID or null if no match was found 
        /// 
        internal RoutedEvent GetRoutedEvent( 
            Type   owner, 
            string xmlNamespace,
            string localName) 
        {
            Type baseType = null;
            string dynamicObjectName = null;
 
            if(null == localName)
            { 
                throw new ArgumentNullException( "localName" ); 
            }
            if(null == xmlNamespace) 
            {
                throw new ArgumentNullException( "xmlNamespace" );
            }
            if (owner != null && !ReflectionHelper.IsPublicType(owner)) 
            {
                _lineNumber = 0;  // Public API, so we don't know the line number. 
                ThrowException(SRID.ParserOwnerEventMustBePublic, owner.FullName ); 
            }
 
            RoutedEvent Event = GetDependencyObject(true,owner,xmlNamespace,
                localName,ref baseType,ref dynamicObjectName)
                as RoutedEvent;
 
            return Event;
 
        } 

#endif 

#endregion Events

#region Properties 

#if !PBTCOMPILER 
        /// 
        /// Converts the string representation of an Attribute Value to an appropriate
        /// Type for the Property.  This handles use of type converters and the special 
        /// *prefix:Type.Field syntax for enums, static properties and fields.
        /// 
        ///Target object that the property needs to be set on
        ///Type of the property 
        ///Name of the property.  This is used only for
        ///                       error reporting and some pre-validation 
        ///DependencyProperty or PropertyInfo or FieldInfo. This is used 
        ///         for evaluating the TypeConverter to be used for conversion
        ///Context for the type converter 
        ///Context for enum, field and property resolution
        ///string value of the property the Attribute
        ///typeId of converter to use for paring the attribute value
        /// 
        /// An Object for the attribute value is returned.
        /// Null is returned if no TypeConverter for the Property type. 
        /// 
        //[CodeAnalysis("AptcaMethodsShouldOnlyCallAptcaMethods")] //Tracking Bug: 29647
        internal Object ParseProperty( 
            object                 targetObject,
            Type                   propType,
            string                 propName,
            object                 dpOrPiOrFi, 
            ITypeDescriptorContext typeContext,
            ParserContext          parserContext, 
            string                 value, 
            short                  converterTypeId)
        { 
            _lineNumber = parserContext != null ? parserContext.LineNumber : 0;
            _linePosition = parserContext != null ? parserContext.LinePosition : 0;

            // If value is to be converted to a string, just return the string itself instead of 
            // going needlessly through the TC. But check that the target prop Type can accept strings.
            if (converterTypeId < 0 && ((short)-converterTypeId == (short)KnownElements.StringConverter)) 
            { 
                if (propType == typeof(object) || propType == typeof(string))
                { 
                    return value;
                }
                else
                { 
                    string message = SR.Get(SRID.ParserCannotConvertPropertyValueString, value, propName, propType.FullName);
                    XamlParseException.ThrowException(parserContext, _lineNumber, _linePosition, message, null); 
                } 
            }
 
            Object obj = null;   // Object to return
            TypeConverter typeConvert;

            if (converterTypeId != 0) 
            {
                typeConvert = parserContext.MapTable.GetConverterFromId(converterTypeId, propType, parserContext); 
            } 
            else
            { 
                // NOTE: This may still be a known converter. This is typically the case when adding
                // a text Record. This should also be potentially optimized by resolving & writing out the
                // TC at compile time.
 
                // Reflect for per property type converter or type converter based on the property's type
                typeConvert = GetPropertyConverter(propType, dpOrPiOrFi); 
 
                #if DEBUG
                if( propType.Assembly.FullName == "PresentationFramework" 
                    ||
                    propType.Assembly.FullName == "PresentationCore"
                    ||
                    propType.Assembly.FullName == "WindowsBase" ) 
                {
                    Debug.WriteLine( "Reflected for type converter on " + propType.Name + "." + propName ); 
                } 
                #endif
            } 

#if !STRESS
            try
            { 
#endif
                obj =  typeConvert.ConvertFromString(typeContext, TypeConverterHelper.InvariantEnglishUS, value); 
 
                if( TraceMarkup.IsEnabled )
                { 
                    TraceMarkup.TraceActivityItem( TraceMarkup.TypeConvert,
                                                 typeConvert,
                                                 value,
                                                 obj ); 
                }
#if !STRESS 
            } 
            catch (Exception e)
            { 
                if( CriticalExceptions.IsCriticalException(e) || e is XamlParseException )
                {
                    throw;
                } 

                // If the targetObject can provide a fallback value for this property then use that instead 
 
                IProvidePropertyFallback iProvidePropertyFallback = targetObject as IProvidePropertyFallback;
                if (iProvidePropertyFallback != null && iProvidePropertyFallback.CanProvidePropertyFallback(propName)) 
                {
                    obj = iProvidePropertyFallback.ProvidePropertyFallback(propName, e);

                    if( TraceMarkup.IsEnabled ) 
                    {
                        TraceMarkup.TraceActivityItem( TraceMarkup.TypeConvertFallback, 
                                                     typeConvert, 
                                                     value,
                                                     obj ); 
                    }
                }

                // If we got the default object TypeConverter, then we know the conversion will 
                // fail, so create a more meaningful error message here.
                else if (typeConvert.GetType() == typeof(TypeConverter)) 
                { 
                    string message;
                    if( propName != string.Empty ) 
                    {
                        //  and there's no TypeConverter
                        //  to handle converting "SomeText" into an instance of something
                        //  that can be set into SomeProp. 
                        message = SR.Get(SRID.ParserDefaultConverterProperty, propType.FullName, propName, value);
                    } 
                    else 
                    {
                        // SomeText and there's no TypeConverter 
                        //  associated with the type SomeElement
                        message = SR.Get(SRID.ParserDefaultConverterElement, propType.FullName, value);
                    }
                    XamlParseException.ThrowException(parserContext, _lineNumber, _linePosition, message, null); 
                }
                else 
                { 
                    string message = TypeConverterFailure( value, propName, propType.FullName );
                    XamlParseException.ThrowException(parserContext, _lineNumber, _linePosition, message, e); 
                }
            }
#endif
 
            // Verify that the type converter actually gave us an instance of the correct object type.
            if( obj != null ) 
            { 
                if(!propType.IsAssignableFrom(obj.GetType()))
                { 
                    string message = TypeConverterFailure( value, propName, propType.FullName );

                    XamlParseException.ThrowException(parserContext, _lineNumber, _linePosition, message, null);
                } 
            }
 
            return obj; 
        }
 
        private string TypeConverterFailure( string value, string propName, string propType )
        {
            string message;
 
            if( propName != string.Empty )
            { 
                // We were called to do type conversion on a string that's been 
                //  assigned in an element attribute, but failed for whatever reason.
                // 
                //   
                //
                // propName is 'Fill' in this case.
 
                message = SR.Get(SRID.ParserCannotConvertPropertyValueString, value, propName, propType);
            } 
            else 
            {
                // We are being called by BamlRecordReader::GetObjectFromString 
                //  which is not trying to convert a property. It's actually
                //  trying to get an element out of this.
                //
                //   Red 
                //
                // There is no associated propName available in this case, so we 
                //  give a different error message. 

                message = SR.Get(SRID.ParserCannotConvertInitializationText, value, propType ); 
            }
            return message;
        }
#endif 

        // ValidateNames does Name validation, and ValidateEnums does enum 
        // name validation.  Note that both must be called to determine if a 
        // property is valid before it is set, but the order is not important.  Hence
        // ValidateNames can be called before writing out a BAML record, and 
        // ValidateEnums can be called later after the BAML record has been read.


        ///  
        /// Validate the Name property.
        /// This will throw an exception if the property is an 
        /// Name that does not follow the rules of only letters, digits and underscores in 
        /// Name names.
        ///  
        internal void ValidateNames(
            string   value,
            int      lineNumber,
            int      linePosition) 
        {
            // set the linenumber and position 
            _lineNumber = lineNumber; 
            _linePosition = linePosition;
 
            if (value == string.Empty)
            {
                ThrowException(SRID.ParserBadName, value);
            } 

            if (MarkupExtensionParser.LooksLikeAMarkupExtension(value)) 
            { 
                string message = SR.Get(SRID.ParserBadUidOrNameME, value);
                message += " "; 
                message += SR.Get(SRID.ParserLineAndOffset,
                            lineNumber.ToString(CultureInfo.CurrentCulture),
                            linePosition.ToString(CultureInfo.CurrentCulture));
 
                XamlParseException parseException = new XamlParseException(message, lineNumber, linePosition);
 
                throw parseException; 
            }
 
            if (!NameValidationHelper.IsValidIdentifierName(value))
            {
                ThrowException(SRID.ParserBadName, value);
            } 
        }
 
        ///  
        /// Validate that if the type converter is
        /// for enums you can't pass numbers to it. 
        /// 
        internal void ValidateEnums(
            string        propName,
            Type          propType, 
            string        attribValue)
        { 
            if (propType.IsEnum && attribValue != string.Empty) 
            {
                // Handle enum strings of the form "one, two, three".  Check that 
                // each of the values does NOT start with a digit.  This doesn't
                // validate that the enum is correct, just that there are no digits
                // specified.
                bool lookingForComma = false; 
                for (int i = 0; i < attribValue.Length; i++)
                { 
                    if (!Char.IsWhiteSpace(attribValue[i])) 
                    {
                        if (lookingForComma) 
                        {
                            if (attribValue[i] == ',')
                            {
                                lookingForComma = false; 
                            }
                        } 
                        else if (Char.IsDigit(attribValue[i])) 
                        {
                            ThrowException(SRID.ParserNoDigitEnums, propName, attribValue); 
                        }
                        else
                        {
                            lookingForComma = true; 
                        }
                    } 
                } 
            }
        } 

        /// 
        /// Get cached member info for the property name.  This can be
        /// a PropertyInfo for the property or a MethodInfo for the static 
        /// setter.  This does not work for EventInfo, so don't call it.
        ///  
        /// Type of the owner of the property  
        /// Name of the property
        /// True if the caller wants the PropertyInfo for the 
        ///     case where both a MethodInfo and propertyInfo are cached for this property
        /// 
        /// The attribute info record retrieved from
        ///     the map table, if one is found.  
        /// 
        /// There is only one scenario under which two memberInfo need to be 
        /// cached for a given attribute. This is the case when there are both a 
        /// Clr wrapper and static Settor for a given DP. In that case we cache
        /// an object array of two elements. Also the MethodInfo for the given DP 
        /// will be discovered first by the XamlReaderHelper while the PropertyInfo
        /// will be discovered by the BamlRecordWriter.
        /// 
        private MemberInfo GetCachedMemberInfo( 
               Type                    owner,
               string                  propName, 
               bool                    onlyPropInfo, 
           out BamlAttributeInfoRecord infoRecord)
        { 
            infoRecord = null;
            if (MapTable != null)
            {
                string fullName = owner.IsGenericType ? owner.Namespace + "." + owner.Name : owner.FullName; 
                object key = MapTable.GetAttributeInfoKey(fullName, propName);
                infoRecord = MapTable.GetHashTableData(key) as BamlAttributeInfoRecord; 
 
                if (infoRecord != null)
                { 
                    return infoRecord.GetPropertyMember(onlyPropInfo) as MemberInfo;
                }
            }
            return null; 
        }
 
#if !PBTCOMPILER 
        /// 
        /// Add cached member info for the property name. 
        /// 
        private void AddCachedAttributeInfo(
               Type                    ownerType,
               BamlAttributeInfoRecord infoRecord) 
        {
            if (MapTable != null) 
            { 
                object key = MapTable.GetAttributeInfoKey(ownerType.FullName, infoRecord.Name);
                MapTable.AddHashTableData(key, infoRecord); 
            }
        }

        ///  
        /// Helper function for getting Clr PropertyInfo on a type and updating the
        /// passed attribute info record.  Also update the property cache with this 
        /// attribute information if it was not already present. 
        /// 
        ///  
        /// Note that the ObjectHashTable may contain
        /// a BamlAttributeInfoRecord from a previous parse for the same property.  If
        /// we find one in the hash table, use its property info instead of reflecting.
        ///  
        internal void UpdateClrPropertyInfo(
            Type currentParentType, 
            BamlAttributeInfoRecord attribInfo) 
        {
            Debug.Assert(null != attribInfo, "null attribInfo"); 
            Debug.Assert(null != currentParentType, "null currentParentType");

            bool isInternal = false;
            string propName = attribInfo.Name; 

            BamlAttributeInfoRecord cachedInfoRecord; 
            attribInfo.PropInfo = GetCachedMemberInfo(currentParentType, propName, true, out cachedInfoRecord) 
                as PropertyInfo;
 
            if (attribInfo.PropInfo == null)
            {
                // If no cached property info, use the slow route of reflecting to get
                // the property info. 
                attribInfo.PropInfo = PropertyInfoFromName(propName, currentParentType, !ReflectionHelper.IsPublicType(currentParentType), false, out isInternal);
                attribInfo.IsInternal = isInternal; 
                if (attribInfo.PropInfo != null) 
                {
                    // If we successfully find a property info via reflection, cache it. 
                    if (cachedInfoRecord != null)
                    {
                        cachedInfoRecord.SetPropertyMember(attribInfo.PropInfo);
                        cachedInfoRecord.IsInternal = attribInfo.IsInternal; 
                    }
                    else 
                    { 
                        AddCachedAttributeInfo(currentParentType, attribInfo);
                    } 
                }
            }
            else
            { 
                attribInfo.IsInternal = cachedInfoRecord.IsInternal;
            } 
        } 

        private void UpdateAttachedPropertyMethdodInfo(BamlAttributeInfoRecord attributeInfo, bool isSetter) 
        {
            MethodInfo attachedPropertyInfo = null;
            Type propertyOwnerType = attributeInfo.OwnerType;
            Debug.Assert(propertyOwnerType != null); 
            bool tryInternal = !ReflectionHelper.IsPublicType(propertyOwnerType);
            string propName = (isSetter ? "Set" : "Get") + attributeInfo.Name; 
            BindingFlags flags = BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy; 

            // Check Set\GetFoo method presence 

            try
            {
                if (!tryInternal) 
                {
                    // first try public methods 
                    attachedPropertyInfo = propertyOwnerType.GetMethod(propName, flags); 
                }
 
                if (attachedPropertyInfo == null)
                {
                    // if public method not found, try non-public method next.
                    attachedPropertyInfo = propertyOwnerType.GetMethod(propName, flags | BindingFlags.NonPublic); 
                }
            } 
            catch (AmbiguousMatchException) 
            {
            } 

            int paramCount = isSetter ? 2 : 1;
            if (attachedPropertyInfo != null && attachedPropertyInfo.GetParameters().Length == paramCount)
            { 
                // the MethodInfo has to be public or internal.
                Debug.Assert(attachedPropertyInfo.IsPublic || 
                                 attachedPropertyInfo.IsAssembly || 
                                 attachedPropertyInfo.IsFamilyOrAssembly);
 
                if (isSetter)
                {
                    attributeInfo.AttachedPropertySetter = attachedPropertyInfo;
                } 
                else
                { 
                    attributeInfo.AttachedPropertyGetter = attachedPropertyInfo; 
                }
            } 
        }

        internal void UpdateAttachedPropertySetter(BamlAttributeInfoRecord attributeInfo)
        { 
            if (attributeInfo.AttachedPropertySetter == null)
            { 
                UpdateAttachedPropertyMethdodInfo(attributeInfo, true); 
            }
        } 

        internal void UpdateAttachedPropertyGetter(BamlAttributeInfoRecord attributeInfo)
        {
            if (attributeInfo.AttachedPropertyGetter == null) 
            {
                UpdateAttachedPropertyMethdodInfo(attributeInfo, false); 
            } 
        }
 
#endif

        /// 
        /// Common helper method to resolve an xml XmlNamespace and LocalName to 
        /// either a EventInfo or a PropertyInfo.
        ///  
        /// True if Event, False look for Property 
        /// Type we should look for attribute on, can be null
        /// XmlNamespace or the Attribute 
        /// local Name of the Attribute
        /// Name of the resolved property or event
        /// PropertyInfo or EventInfo for resolved property or event
        internal MemberInfo GetClrInfo( 
                bool   isEvent,
                Type   owner, 
                string xmlNamespace, 
                string localName,
            ref string propName) 
        {
            Debug.Assert(null != localName, "null localName");
            Debug.Assert(null != xmlNamespace, "null xmlNamespace");
 
            // adjust urtNamespace and localName if there are any periods in the localName.
            string globalClassName = null; 
            int lastIndex = localName.LastIndexOf('.'); 

            if (-1 != lastIndex) 
            {
                // If using .net then match against the class.
                globalClassName = localName.Substring(0, lastIndex);
                localName = localName.Substring(lastIndex+1); 
            }
 
            return GetClrInfoForClass(isEvent, owner, xmlNamespace, localName, globalClassName, ref propName); 
        }
 
#if PBTCOMPILER
        // Checks to see if a given event handler delegate type is accessible.
        static private bool IsAllowedEventDelegateType(Type delegateType)
        { 
            if (!ReflectionHelper.IsPublicType(delegateType))
            { 
                if (!ReflectionHelper.IsInternalType(delegateType) || 
                    !IsInternalAllowedOnType(delegateType))
                { 
                    return false;
                }
            }
 
            return true;
        } 
 
        // Checks to see if a given event's add method is accessible.
        // Checks for protected add methods as well if requested. 
        private bool IsAllowedEvent(EventInfo ei, bool isProtectedAllowed)
        {
            MethodInfo mi = ei.GetAddMethod(true);
            return IsAllowedMethod(mi, isProtectedAllowed); 
        }
 
        // Checks to see if a given property's set method is accessible. 
        // Always checks for protected set methods as well.
        internal bool IsAllowedPropertySet(PropertyInfo pi) 
        {
            MethodInfo mi = pi.GetSetMethod(true);
            return IsAllowedMethod(mi, true);
        } 

        // Checks to see if a given property's get method is accessible. 
        // Checks for protected get methods as well if requested. 
        private bool IsAllowedPropertyGet(PropertyInfo pi, bool checkProtected)
        { 
            MethodInfo mi = pi.GetGetMethod(true);
            return IsAllowedMethod(mi, checkProtected);
        }
 
        // Checks to see if a given property's get method is accessible.
        // Always checks for protected get methods as well. 
        internal bool IsAllowedPropertyGet(PropertyInfo pi) 
        {
            MethodInfo mi = pi.GetGetMethod(true); 
            return IsAllowedMethod(mi, true);
        }

        // Checks to see if a given field member is accessible. 
        private bool IsAllowedField(FieldInfo fi)
        { 
            bool allowed = false; 

            // No field, so not allowed 
            if (fi != null)
            {
                // field is public -- always allow.
                allowed = fi.IsPublic; 
                if (!allowed)
                { 
                    // if not, try accessible internal fields. 
                    // if the field from a base type, then it must be in the same assembly
                    // as the type from which it was reflected. If not, internals will not 
                    // be allowed.
                    if (fi.ReflectedType.Assembly == fi.DeclaringType.Assembly)
                    {
                        // if reflected type is public, check to see if internals are allowed 
                        // on that type (i.e local or friend). If not, the type has to be an
                        // internal allowed type due to the guaranteed central check in 
                        // CreateTypeAndSerializer(). 
                        if (ReflectionHelper.IsPublicType(fi.ReflectedType))
                        { 
                            allowed = IsInternalAllowedOnType(fi.ReflectedType);
                        }
                        else
                        { 
                            allowed = true;
                        } 
 
                        // Either ways, if reflected type is allowed only allow non-public
                        // fields that are internal. 
                        allowed = allowed && (fi.IsAssembly || fi.IsFamilyOrAssembly);
                    }
                }
            } 

            return allowed; 
        } 

        // Checks to see if a given methodInfo (for a property's get\set method 
        // or an event's add method) is accessible.
        private bool IsAllowedMethod(MethodInfo mi, bool checkProtected)
        {
            bool allowed = false; 

            // No method, so not allowed 
            if (mi != null) 
            {
                // method is public -- always allow. 
                allowed = mi.IsPublic;
                if (!allowed)
                {
                    // method is not public. 
                    // Next check to see if the mapper will allow looking for protected
                    // attributes. This will be the case if current methodInfo has been 
                    // reflected off of the markup sub-classed root element, i.e one with 
                    // an x:Class attribute, in which case IsProtectedAttributeAllowed will
                    // be true. So in this case allow protected if caller wishes for this 
                    // by setting the checkProtected param to true.
                    if (checkProtected && IsProtectedAttributeAllowed)
                    {
                        // if so, allow protected or internal protected method. 
                        allowed = mi.IsFamily || mi.IsFamilyOrAssembly;
                    } 
 
                    if (!allowed)
                    { 
                        // if not, try accessible internal methods.
                        // if the property or event inherits from a base type, then its
                        // accessor method must be in the same assembly as the type from
                        // which it was reflected. If not, internals will not be allowed. 
                        if (mi.ReflectedType.Assembly == mi.DeclaringType.Assembly)
                        { 
                            // if reflected type is public, check to see if internals are allowed 
                            // on that type (i.e local or friend). If not, the type has to be an
                            // internal allowed type due to the guaranteed central check in 
                            // CreateTypeAndSerializer().
                            if (ReflectionHelper.IsPublicType(mi.ReflectedType))
                            {
                                allowed = IsInternalAllowedOnType(mi.ReflectedType); 
                            }
                            else 
                            { 
                                allowed = true;
                            } 

                            // Either ways, if reflected type is allowed only allow non-public members
                            // that are internal.
                            allowed = allowed && (mi.IsAssembly || mi.IsFamilyOrAssembly); 
                        }
                    } 
                } 
            }
 
            return allowed;
        }
#else
        // Checks to see if a given property's set method is public. 
        // Used only in Xaml Load sceanrios.
        internal bool IsAllowedPropertySet(PropertyInfo pi) 
        { 
            MethodInfo mi = pi.GetSetMethod(true);
            return (mi != null && mi.IsPublic); 
        }

        // Checks to see if a given property's get method is public.
        // Used only in Xaml Load sceanrios. 
        internal bool IsAllowedPropertyGet(PropertyInfo pi)
        { 
            MethodInfo mi = pi.GetGetMethod(true); 
            return (mi != null && mi.IsPublic);
        } 

        // Checks to see if a given property's set method is accessible.
        // Used only in compiled Baml Load sceanrios.
        static internal bool IsAllowedPropertySet(PropertyInfo pi, bool allowProtected, out bool isPublic) 
        {
            MethodInfo mi = pi.GetSetMethod(true); 
            bool isProtected = allowProtected && mi != null && mi.IsFamily; 
            // return isPublic == true only if the property is public on a base declaring Type.
            // if the property is public on the reflected internal type itself, then we still 
            // need to call the generated helper to set the property.
            isPublic = mi != null && mi.IsPublic && ReflectionHelper.IsPublicType(mi.DeclaringType);
            return (mi != null && (mi.IsPublic || mi.IsAssembly || mi.IsFamilyOrAssembly || isProtected));
        } 

        // Checks to see if a given property's get method is accessible. 
        // Used only in compiled Baml Load sceanrios. 
        static private bool IsAllowedPropertyGet(PropertyInfo pi, bool allowProtected, out bool isPublic)
        { 
            MethodInfo mi = pi.GetGetMethod(true);
            bool isProtected = allowProtected && mi != null && mi.IsFamily;
            // return isPublic == true only if the property is public on a base declaring Type.
            // if the property is public on the reflected internal type itself, then we still 
            // need to call the generated helper to get the property.
            isPublic = mi != null && mi.IsPublic && ReflectionHelper.IsPublicType(mi.DeclaringType); 
            return (mi != null && (mi.IsPublic || mi.IsAssembly || mi.IsFamilyOrAssembly || isProtected)); 
        }
 
        // Checks to see if a given event's add method is accessible.
        // Used only in compiled Baml Load sceanrios.
        static private bool IsAllowedEvent(EventInfo ei, bool allowProtected, out bool isPublic)
        { 
            MethodInfo mi = ei.GetAddMethod(true);
            bool isProtected = allowProtected && mi != null && mi.IsFamily; 
            // return isPublic == true only if the event is public on a base declaring Type. 
            // if the event is public on the reflected internal type itself, then we still
            // need to call the generated helper to hook up the event. 
            isPublic = mi != null && mi.IsPublic && ReflectionHelper.IsPublicType(mi.DeclaringType);
            return (mi != null && (mi.IsPublic || mi.IsAssembly || mi.IsFamilyOrAssembly || isProtected));
        }
#endif 

        // Checks to see if a given event's add method is public. 
        // Used in all (xaml load, xaml compile & compiled Baml Load sceanrios. 
        static private bool IsPublicEvent(EventInfo ei)
        { 
            MethodInfo mi = ei.GetAddMethod(true);
            return (mi != null && mi.IsPublic);
        }
 
#if !PBTCOMPILER
        ///  
        /// Allows a sub-classed XamlTypeMapper called under Full Trust to participate 
        /// in deciding if an internal type should be accessible.
        ///  
        /// The internal type
        /// 
        /// When overriden, should return true if accessible, false if not.
        /// Returns false by default, if no one overrides. 
        /// 
        protected virtual bool AllowInternalType(Type type) 
        { 
            return false;
        } 

        private bool IsInternalTypeAllowedInFullTrust(Type type)
        {
            bool isAllowed = false; 
            // If caller has Full Trust and the type is internal, then allow them to participate
            // in deciding if that internal type should be accessible. 
            if (ReflectionHelper.IsInternalType(type) && MS.Internal.SecurityHelper.IsFullTrustCaller()) 
            {
                isAllowed = AllowInternalType(type); 
            }

            return isAllowed;
        } 
#endif
 
        ///  
        /// Common helper method to resolve an xml XmlNamespace and LocalName to
        /// either a EventInfo or a PropertyInfo. 
        /// 
        /// True if Event, False look for Property
        /// Type we should look for attribute on, can be null
        /// XmlNamespace or the Attribute 
        /// local Name of the Attribute with no class
        /// Class Name of the Attribute, or null if not present 
        /// Name of the resolved property or event 
        /// PropertyInfo or EventInfo for resolved property or event
        internal MemberInfo GetClrInfoForClass ( 
                bool   isEvent,
                Type   owner,
                string xmlNamespace,
                string localName, 
                string globalClassName,
            ref string propName) 
        { 
            MemberInfo mi = null;
#if PBTCOMPILER 
            if (owner == null || ReflectionHelper.IsPublicType(owner))
            {
#endif
            // first, try normal lookup for public properties and events only. 
                mi = GetClrInfoForClass(isEvent, owner, xmlNamespace, localName, globalClassName, false, ref propName);
#if PBTCOMPILER 
            } 

            if (mi == null && owner != null) 
            {
                // if lookup on internal type or if public property or event lookup failed,
                // try internal ones as well, or protected if the type happens to be a
                // code-generated root. 
                mi = GetClrInfoForClass(isEvent, owner, xmlNamespace, localName, globalClassName, true, ref propName);
            } 
#endif 

            return mi; 
        }

        private MemberInfo GetClrInfoForClass(
                bool isEvent, 
                Type owner,
                string xmlNamespace, 
                string localName, 
                string globalClassName,
                bool tryInternal, 
            ref string propName)
        {
            bool isInternal = false;
            MemberInfo memberInfo = null; 
            BindingFlags defaultBinding = BindingFlags.Public;
 
#if PBTCOMPILER 
            if (tryInternal)
            { 
                defaultBinding |= BindingFlags.NonPublic;
            }
#endif
 
            propName = null;
            ParameterInfo[] pis = null; 
 
            // if this is a globalClass then resolve the type and then call the dpFromName
            if (null != globalClassName) 
            {
                TypeAndSerializer typeAndSerializer =
                    GetTypeOnly(xmlNamespace, globalClassName);
 
                if (typeAndSerializer != null && typeAndSerializer.ObjectType != null)
                { 
                    BamlAttributeInfoRecord infoRecord; 
                    Type objectType = typeAndSerializer.ObjectType;
                    memberInfo = GetCachedMemberInfo(objectType, localName, false, out infoRecord); 

                    if (memberInfo == null)
                    {
                        if (isEvent) 
                        {
                            // See if attached event first 
                            memberInfo = objectType.GetMethod("Add" + localName + "Handler", 
                                defaultBinding |
                                BindingFlags.Static | 
                                BindingFlags.FlattenHierarchy);

                            // Make sure that we found a method of the right signature.
                            // Otherwise discard what you found. 
                            if (memberInfo != null)
                            { 
                                MethodInfo mi = memberInfo as MethodInfo; 
                                if (mi != null)
                                { 
                                    pis = mi.GetParameters();
                                    Type dependencyObjectType = KnownTypes.Types[(int)KnownElements.DependencyObject];
                                    if (pis == null || pis.Length != 2 || !dependencyObjectType.IsAssignableFrom(pis[0].ParameterType))
                                    { 
                                        memberInfo = null;
                                    } 
#if PBTCOMPILER 
                                    if (tryInternal && memberInfo != null && !IsAllowedMethod(mi, false))
                                    { 
                                        ThrowException(SRID.ParserCantSetAttribute, "bubbling event", objectType.Name + "." + localName, "Add Handler method");
                                    }
#endif
                                } 
                            }
 
                            // 
                            if (memberInfo == null)
                            { 
                                // Not an attached event so try Clr event
                                memberInfo = objectType.GetEvent(localName,
                                    defaultBinding |
                                    BindingFlags.Instance | 
                                    BindingFlags.FlattenHierarchy);
 
                                if (memberInfo != null) 
                                {
                                    EventInfo ei = memberInfo as EventInfo; 
#if PBTCOMPILER
                                    if (!IsAllowedEventDelegateType(ei.EventHandlerType))
#else
                                    if (!ReflectionHelper.IsPublicType(ei.EventHandlerType)) 
#endif
                                    { 
                                        ThrowException(SRID.ParserEventDelegateTypeNotAccessible, ei.EventHandlerType.FullName, objectType.Name + "." + localName); 
                                    }
 
#if PBTCOMPILER
                                    if (tryInternal)
                                    {
                                        // Check if the event add method accessor itself is accessible. 
                                        // Also if this is a non-public event on a public type, it will
                                        // check to make sure that the public type is accessible\allowed. 
                                        if (!IsAllowedEvent(ei, false)) 
                                        {
                                            ThrowException(SRID.ParserCantSetAttribute, "event", objectType.Name + "." + localName, "add"); 
                                        }
                                    }
                                    else
                                    { 
#endif
                                        // Check if the event add method accessor itself is public. 
                                        if (!IsPublicEvent(ei)) 
                                        {
#if PBTCOMPILER 
                                            memberInfo = null;
#else
                                            ThrowException(SRID.ParserCantSetAttribute, "event", objectType.Name + "." + localName, "add");
#endif 
                                        }
#if PBTCOMPILER 
                                    } 
#endif
                                } 
                            }
                        }
                        else
                        { 

                            // See if attached property first - start from a Setter 
                            memberInfo = objectType.GetMethod("Set" + localName, 
                                defaultBinding |
                                BindingFlags.Static | 
                                BindingFlags.FlattenHierarchy);
                            if (memberInfo != null && ((MethodInfo)memberInfo).GetParameters().Length != 2)
                            {
                                memberInfo = null; 
                            }
                            // Try read-only case (Getter only) 
                            if (memberInfo == null) 
                            {
                                memberInfo = objectType.GetMethod("Get" + localName, 
                                    defaultBinding |
                                    BindingFlags.Static |
                                    BindingFlags.FlattenHierarchy);
                                if (memberInfo != null && ((MethodInfo)memberInfo).GetParameters().Length != 1) 
                                {
                                    memberInfo = null; 
                                } 
                            }
 
#if PBTCOMPILER
                            if (tryInternal && memberInfo != null && !IsAllowedMethod(memberInfo as MethodInfo, false))
                            {
                                ThrowException(SRID.ParserCantSetAttribute, "attached property", objectType.Name + "." + localName, "Set method"); 
                            }
#endif 
 
                            //
                            if (memberInfo == null) 
                            {
                                // Not an attached property, so try clr property
                                memberInfo = PropertyInfoFromName(localName, objectType, tryInternal, true, out isInternal);
 
                                // If we've found a property info, then the owner had better
                                // be the same type as or a subclass of the objectType, or 
                                // they are in different inheritance hierarchies.  This 
                                // fixes windows bug 920135.
                                if (memberInfo != null) 
                                {
                                    if (owner != null &&
                                        !objectType.IsAssignableFrom(owner))
                                    { 
                                        ThrowException(SRID.ParserAttachedPropInheritError,
                                                       String.Format(CultureInfo.CurrentCulture, "{0}.{1}", objectType.Name, localName), 
                                                       owner.Name); 
                                    }
                                } 
                            }

                            if (null != memberInfo)
                            { 
                                if (infoRecord != null)
                                { 
#if !PBTCOMPILER 
                                    // DP's aren't present in the PBT case
                                    if (infoRecord.DP == null) 
                                    {
                                        infoRecord.DP = MapTable.GetDependencyProperty(infoRecord);
                                    }
#endif 
                                    infoRecord.SetPropertyMember(memberInfo);
                                } 
                            } 
                        }
                    } 
                }
            }
            else if (null != owner)
            { 
                Type baseType = owner;
 
                // See if the owner knows about this class. 
                // Look for a parent type until we find a match or fail.
                if (null != baseType) 
                {
                    BamlAttributeInfoRecord infoRecord;
                    memberInfo = GetCachedMemberInfo(baseType, localName, false, out infoRecord);
 
                    if (memberInfo == null)
                    { 
                        if (isEvent) 
                        {
                            // See if attached event first 
                            memberInfo = baseType.GetMethod("Add" + localName + "Handler",
                                defaultBinding | BindingFlags.Static | BindingFlags.FlattenHierarchy);

                            // Make sure that we found a method of the right signature. 
                            // Otherwise discard what you found.
                            if (memberInfo != null) 
                            { 
                                MethodInfo mi = memberInfo as MethodInfo;
                                if (mi != null) 
                                {
                                    pis = mi.GetParameters();
                                    Type dependencyObjectType = KnownTypes.Types[(int)KnownElements.DependencyObject];
                                    if (pis == null || pis.Length != 2 || !dependencyObjectType.IsAssignableFrom(pis[0].ParameterType)) 
                                    {
                                        memberInfo = null; 
                                    } 
#if PBTCOMPILER
                                    if (tryInternal && memberInfo != null && !IsAllowedMethod(mi, true)) 
                                    {
                                        ThrowException(SRID.ParserCantSetAttribute, "bubbling event", owner.Name + "." + localName, "Add Handler method");
                                    }
#endif 
                                }
                            } 
 
                            if (memberInfo == null)
                            { 
                                // Not an attached event, so try for a clr event.
                                memberInfo = baseType.GetEvent(localName,
                                    BindingFlags.Instance | BindingFlags.FlattenHierarchy | defaultBinding);
 
                                if (memberInfo != null)
                                { 
                                    EventInfo ei = memberInfo as EventInfo; 
#if PBTCOMPILER
                                    if (!IsAllowedEventDelegateType(ei.EventHandlerType)) 
#else
                                    if (!ReflectionHelper.IsPublicType(ei.EventHandlerType))
#endif
                                    { 
                                        ThrowException(SRID.ParserEventDelegateTypeNotAccessible, ei.EventHandlerType.FullName, owner.Name + "." + localName);
                                    } 
 
#if PBTCOMPILER
                                    if (tryInternal) 
                                    {
                                        // Check if the event add method accessor itself is accessible.
                                        // Also if this is a non-public event on a public type, it will
                                        // not check to make sure that the public type is accessible\allowed 
                                        // since that would have all ready been done in the caller of this fucntion.
                                        if (!IsAllowedEvent(ei, true)) 
                                        { 
                                            ThrowException(SRID.ParserCantSetAttribute, "event", owner.Name + "." + localName, "add");
                                        } 
                                    }
                                    else
                                    {
#endif 
                                        // check if the event add method accessor itself is public.
                                        if (!IsPublicEvent(ei)) 
                                        { 
#if PBTCOMPILER
                                            memberInfo = null; 
#else
                                            ThrowException(SRID.ParserCantSetAttribute, "event", owner.Name + "." + localName, "add");
#endif
                                        } 
#if PBTCOMPILER
                                    } 
#endif 
                                }
                            } 
                        }
                        else
                        {
                            // See if attached property first - start from a Setter 
                            memberInfo = baseType.GetMethod("Set" + localName,
                                defaultBinding | 
                                BindingFlags.Static | 
                                BindingFlags.FlattenHierarchy);
                            if (memberInfo != null && ((MethodInfo)memberInfo).GetParameters().Length != 2) 
                            {
                                memberInfo = null;
                            }
                            // Try read-only case (Getter only) 
                            if (memberInfo == null)
                            { 
                                memberInfo = baseType.GetMethod("Get" + localName, 
                                    defaultBinding |
                                    BindingFlags.Static | 
                                    BindingFlags.FlattenHierarchy);
                                if (memberInfo != null && ((MethodInfo)memberInfo).GetParameters().Length != 1)
                                {
                                    memberInfo = null; 
                                }
                            } 
 
#if PBTCOMPILER
                            if (tryInternal && memberInfo != null && !IsAllowedMethod(memberInfo as MethodInfo, true)) 
                            {
                                ThrowException(SRID.ParserCantSetAttribute, "attached property", owner.Name + "." + localName, "Set method");
                            }
#endif 

                            if (memberInfo == null) 
                            { 
                                // Not an attached property, so try for a clr property.
                                memberInfo = PropertyInfoFromName(localName, baseType, tryInternal, true, out isInternal); 
                            }

                            if (null != memberInfo)
                            { 
                                if (infoRecord != null)
                                { 
#if !PBTCOMPILER 
                                    // DP's aren't present in the PBT case
                                    if (infoRecord.DP == null) 
                                    {
                                        infoRecord.DP = MapTable.GetDependencyProperty(infoRecord);
                                    }
#endif 
                                    infoRecord.SetPropertyMember(memberInfo);
                                } 
                            } 
                        }
                    } 
                }
            }

            if (null != memberInfo) 
            {
                propName = localName; 
            } 

            return memberInfo; 
        }

#if !PBTCOMPILER
        ///  
        /// Helper method to get an event on an owner, walking up the class hierarchy
        /// when doing so 
        ///  
        /// Type we should look for the event on
        /// Then name of the handler of the event 
        /// EventInfo for resolved event
        internal EventInfo GetClrEventInfo(
            Type   owner,
            string eventName) 
        {
            Debug.Assert(null != eventName, "null eventName"); 
            Debug.Assert(null != owner, "null owner"); 

            EventInfo eventInfo = null; 

            // Look up the parent chain until we find a match or fail by
            // going off the top of the chain.
            while (owner != null) 
            {
                eventInfo = owner.GetEvent(eventName, BindingFlags.Instance | BindingFlags.Public); 
                if (eventInfo != null) 
                {
                    break; 
                }

                owner = GetCachedBaseType(owner);
            } 

            return eventInfo; 
        } 

        ///  
        /// Helper method to resolve an xml namespace and localName to
        /// either a RoutedEvent or a DependencyProperty.  If they are not present,
        /// still resolve using a guess at the valid setter name to look for.
        ///  
        /// 
        ///  Note that this will not resolve clr properties.  Call GetClrInfo to do that. 
        ///  
        /// True if Event, False look for Property
        /// Type we should look for attribute on, can be null 
        /// XmlNamespace or the Attribute
        /// local Name of the Attribute
        /// Base type the object was found on
        /// registered name of the Object on the type. 
        /// resolved object, which can be a RoutedEvent, a DependencyProperty
        ///          or the MethodInfo for the event or property setter 
        internal object GetDependencyObject( 
                bool       isEvent,
                Type       owner, 
                string     xmlNamespace,
                string     localName,
            ref Type       baseType,
            ref string     dynamicObjectName) 
        {
            Debug.Assert(null != localName, "null localName"); 
            Debug.Assert(null != xmlNamespace, "null xmlNamespace"); 

            object memInfo = null; 
            string globalClassName = null;

            dynamicObjectName = null;
 
            // Extract the class name if there are any periods in the localName.
            int lastIndex = localName.LastIndexOf('.'); 
            if (-1 != lastIndex) 
            {
                // if using .net then match against the class. 
                globalClassName = localName.Substring(0,lastIndex);
                localName = localName.Substring(lastIndex+1);
            }
 
            // If this is a globalClassName then resolve the type and then call
            // DependencyProperty.FromName. 
            if (null != globalClassName) 
            {
                TypeAndSerializer typeAndSerializer = 
                    GetTypeOnly(xmlNamespace,globalClassName);

                if (typeAndSerializer != null && typeAndSerializer.ObjectType != null)
                { 
                    baseType = typeAndSerializer.ObjectType;
                    if (isEvent) 
                    { 
                        memInfo = RoutedEventFromName(localName,baseType);
                    } 
                    else
                    {
                        memInfo = DependencyProperty.FromName(localName, baseType);
 
                    }
 
                    if (null != memInfo) 
                    {
                        Debug.Assert(null != baseType, "baseType not set"); 
                        dynamicObjectName = localName;
                    }
                }
            } 
            else
            { 
                NamespaceMapEntry[] namespaceMaps = GetNamespaceMapEntries(xmlNamespace); 

                if (null == namespaceMaps) 
                {
                    return null;
                }
 
                baseType = owner;
 
                // See if the owner knows about this class. 
                // Look for a parent type with any namespace matching the property
                while (null != baseType) 
                {
                    bool foundNamespaceMatch = false;

                    // Look at each namespace for a match with this baseType 
                    for (int count = 0;
                         count < namespaceMaps.Length && !foundNamespaceMatch; 
                         count ++) 
                    {
                        NamespaceMapEntry namespaceMap = namespaceMaps[count]; 

                        // see if the urtNamespace in the namespace map is valid
                        // for the type we are trying to apply
                        if (namespaceMap.ClrNamespace == GetCachedNamespace(baseType)) 
                        {
                            foundNamespaceMatch = true; 
                        } 
                    }
 
                    if (foundNamespaceMatch)
                    {
                        // For 'normal' properties and events that are not prefixed by
                        // a class name, only attempt to get dependency IDs and Events. 
                        // The caller should use GetClrInfo to get CLR properties for
                        // 'normal' properties and events if this attempt fails. 
                        if (isEvent) 
                        {
                            memInfo = RoutedEventFromName(localName,baseType); 
                        }
                        else
                        {
                            memInfo = DependencyProperty.FromName(localName, baseType); 
                        }
                    } 
 
                    // Only do one loop for events, since all base classes are checked in
                    // a single operation.  For properties, loop through the base classes here. 
                    if (null != memInfo || isEvent)
                    {
                        // for assembly and typeName use the original, not the base
                        // type we found it on. 
                        dynamicObjectName = localName;
                        break; 
                    } 
                    else
                    { 
                        baseType = GetCachedBaseType(baseType);
                    }
                }
            } 

            return memInfo; 
        } 

 
         ///
        /// Returns a DependencyProperty given a local name and an xml namespace
        ///
        /// 
        /// The property name
        /// 
        /// 
        /// Xml namespace associated with name
        /// 
        ///
        /// The Type where this DP was registered.
        ///
        /// 
        /// Returns a DependencyProperty the attached property
        /// 
        internal DependencyProperty DependencyPropertyFromName( 
                string localName,
                string xmlNamespace, 
            ref Type   ownerType)
         {
             Debug.Assert(null != localName, "null localName");
             Debug.Assert(null != xmlNamespace, "null xmlNamespace"); 

            // Adjust localName if there are any periods that indicate a global class.  Use 
            // this class name as the owner type and return it.  Otherwise just use the 
            // passed name and owner.
            int lastIndex = localName.LastIndexOf('.'); 
            if (-1 != lastIndex)
            {
                string globalClassName = localName.Substring(0,lastIndex);
                localName = localName.Substring(lastIndex+1); 
                TypeAndSerializer typeAndSerializer =
                    GetTypeOnly(xmlNamespace, globalClassName); 
                if (typeAndSerializer == null || typeAndSerializer.ObjectType == null) 
                {
                    ThrowException(SRID.ParserNoType, globalClassName); 
                }
                ownerType = typeAndSerializer.ObjectType;
            }
 
            if(null == ownerType)
            { 
                throw new ArgumentNullException( "ownerType" ); 
            }
 
            return DependencyProperty.FromName(localName, ownerType);
        }

#endif 

        ///  
        /// Return the property that has an attached XmlLang attribute.  This identifies this 
        /// property as being the one to receive xml:lang attribute values when parsing, or
        /// the holder of the CultureInfo related string.  The XamlTypeMapper caches this 
        /// along with the TypeAndSerializer information for fast retrieval.
        /// 
        internal PropertyInfo GetXmlLangProperty(
                string    xmlNamespace,     // xml namespace for the type 
                string    localName)        // local name of the type without any '.'
        { 
            TypeAndSerializer typeAndSerializer = GetTypeOnly(xmlNamespace, localName); 

            if (typeAndSerializer == null || typeAndSerializer.ObjectType == null) 
            {
                return null;
            }
 
            if (typeAndSerializer.XmlLangProperty == null)
            { 
                BamlAssemblyInfoRecord bairPF = MapTable.GetAssemblyInfoFromId(-1); 

                if (typeAndSerializer.ObjectType.Assembly == bairPF.Assembly) 
                {
                    if (KnownTypes.Types[(int)KnownElements.FrameworkElement].IsAssignableFrom(typeAndSerializer.ObjectType) ||
                        KnownTypes.Types[(int)KnownElements.FrameworkContentElement].IsAssignableFrom(typeAndSerializer.ObjectType))
                    { 
                        typeAndSerializer.XmlLangProperty = (KnownTypes.Types[(int)KnownElements.FrameworkElement]).GetProperty("Language",
                            BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy); 
                    } 
                }
                else 
                {
                    string xmlLangPropertyName = null;
                    bool   xmlLangPropertyFound = false;
 
#if !PBTCOMPILER
                    AttributeCollection attributes = TypeDescriptor.GetAttributes(typeAndSerializer.ObjectType); 
 
                    if (attributes != null)
                    { 
                        XmlLangPropertyAttribute xlpa = attributes[typeof(XmlLangPropertyAttribute)] as XmlLangPropertyAttribute;
                        if (xlpa != null)
                        {
                            xmlLangPropertyFound = true; 
                            xmlLangPropertyName = xlpa.Name;
                        } 
                    } 
#else
                    Type typeValue = null; 
                    xmlLangPropertyName = ReflectionHelper.GetCustomAttributeData(typeAndSerializer.ObjectType,
                                                                                  KnownTypes.Types[(int)KnownElements.XmlLangPropertyAttribute],
                                                                                  false,
                                                                              ref xmlLangPropertyFound, 
                                                                              out typeValue);
#endif 
 
                    if ( xmlLangPropertyFound )
                    { 
                        if( xmlLangPropertyName != null && xmlLangPropertyName.Length > 0)
                        {
                            typeAndSerializer.XmlLangProperty = typeAndSerializer.ObjectType.GetProperty(
                                xmlLangPropertyName, 
                                BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
                        } 
 
                        if( typeAndSerializer.XmlLangProperty == null )
                        { 
                            // Either the given name could not be found, or there
                            //  was no name specified at all.  (null or empty string.)
                            // The latter case may get a special meaning in the future,
                            //  but for now they're all errors. 
                            ThrowException(SRID.ParserXmlLangPropertyValueInvalid);
                        } 
                    } 
                }
            } 

            return typeAndSerializer.XmlLangProperty;
        }
 
        ///
        /// Returns a PropertyInfo from an attribute name, given the ownerType of 
        /// the property. 
        ///
        /// 
        /// The attribute name
        ///
        ///
        /// The Type that owns the attribute 
        ///
        /// 
        /// Indicates if this function should search for non-public properties as well 
        ///
        /// 
        /// Indicates if this function should search for public properties only, regardless
        /// of tryInternal as is the case in XamlLoad sceanrios.
        ///
        /// 
        /// Indicates if this fucntion actually found a non-public property
        /// 
        /// 
        /// Returns a PropertyInfo for the property
        /// 
        private PropertyInfo PropertyInfoFromName(
            string localName,
            Type   ownerType,
            bool tryInternal, 
            bool tryPublicOnly,
            out bool isInternal) 
        { 
            PropertyInfo info = null;
            isInternal = false; 
            TypeInformationCacheData typeInfo = GetCachedInformationForType(ownerType);
            Debug.Assert(typeInfo != null, "Must have cached type info at this point");
            PropertyAndType propAndType = typeInfo.GetPropertyAndType(localName);
 
            // peterost - This is a TEMPORARY workaround to
            //    properties that have been overridden in some classes using the 
            //    "new" operator.  This should be removed when properties such as 
            //    Window.Width and ColumnDefintion.Width are rationalized.
            if (propAndType == null || !propAndType.PropInfoSet) 
            {
                try
                {
                    BindingFlags flags = BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.Public; 
#if PBTCOMPILER
                    if (tryInternal) 
                    { 
                        flags |= BindingFlags.NonPublic;
                    } 
                    info = ownerType.GetProperty(localName, flags);
#else
                    if (!tryInternal)
                    { 
                        info = ownerType.GetProperty(localName, flags);
                    } 
 
                    // Xaml load scenarios should not look for internals - tryPublicOnly == true
                    // If the above load failed then try again looking at internals, unless 
                    // tryPublicOnly tells us not to do that.
                    if (info == null && !tryPublicOnly)
                    {
                        info = ownerType.GetProperty(localName, flags | BindingFlags.NonPublic); 
                        if (info != null)
                        { 
                            isInternal = true; 
                        }
                    } 
#endif
                }
                catch (AmbiguousMatchException)
                { 
                    PropertyInfo[] infos = ownerType.GetProperties(
                                  BindingFlags.Instance | BindingFlags.Public); 
                    for (int i = 0; i < infos.Length; i++) 
                    {
                        if (infos[i].Name == localName) 
                        {
                            info = infos[i];
                            break;
                        } 
                    }
                } 
#if PBTCOMPILER 
                if (tryInternal || info != null)
                { 
#endif
                    typeInfo.SetPropertyAndType(localName, info, ownerType, isInternal);
#if PBTCOMPILER
                } 
#endif
            } 
            else 
            {
                info = propAndType.PropInfo; 
                isInternal = propAndType.IsInternal;
            }

            return info; 
        }
 
#if !PBTCOMPILER 

        /// 
        /// Returns a RoutedEvent from an attribute name
        ///
        ///
        /// The attribute name 
        ///
        /// 
        /// The Type that owns the attribute 
        ///
        /// 
        /// Returns a RoutedEvent for the name
        ///
        internal RoutedEvent RoutedEventFromName(
            string localName, 
            Type   ownerType)
        { 
            RoutedEvent Event = null; 
            Type currentType = ownerType;
 
            // Force load the Statics by walking up the hierarchy and running class constructors
            while (null != currentType)
            {
                MS.Internal.WindowsBase.SecurityHelper.RunClassConstructor(currentType); 
                currentType = GetCachedBaseType(currentType);
            } 
 
            // EventManager takes care of going up the hierarchy, so we don't need to loop here
            // to do it.  Just do one call. 
            Event =  EventManager.GetRoutedEventFromName(localName,ownerType);

            return Event;
       } 
#endif
 
        ///  
        /// Given an object that is either a PropertyInfo, MethodInfo for the static
        /// setter, or DependencyProperty, return the type of the property.  This assumes 
        /// the Avalon rule that a DependencyProperty has a static setter where the
        /// second parameter gives the type of the property.
        /// 
        internal static Type GetPropertyType(object propertyMember) 
        {
            Type propertyType; 
            bool propertyCanWrite; 
            GetPropertyType(propertyMember, out propertyType, out propertyCanWrite);
 
            return propertyType;
        }

        ///  
        /// Given an object that is either a PropertyInfo, MethodInfo for the static
        /// setter, or DependencyProperty, return the type of the property.  This assumes 
        /// the Avalon rule that a DependencyProperty has a static setter where the 
        /// second parameter gives the type of the property.
        ///  
        internal static void GetPropertyType(
            object propertyMember,
        out Type   propertyType,
        out bool   propertyCanWrite) 
        {
// 
#if !PBTCOMPILER 
            DependencyProperty dp = propertyMember as DependencyProperty;
            if (dp != null) 
            {
                propertyType = dp.PropertyType;
                propertyCanWrite = !dp.ReadOnly;
            } 
            else
            { 
#endif 
                PropertyInfo propertyInfo = propertyMember as PropertyInfo;
                if (propertyInfo != null) 
                {
                    propertyType = propertyInfo.PropertyType;
                    propertyCanWrite = propertyInfo.CanWrite;
                } 
                else
                { 
                    MethodInfo methodInfo = propertyMember as MethodInfo; 
                    if (methodInfo != null)
                    { 
                        ParameterInfo[] parameters = methodInfo.GetParameters();
                        propertyType = parameters.Length == 1 ? methodInfo.ReturnType : parameters[1].ParameterType;
                        propertyCanWrite = parameters.Length == 1 ? false : true;
                    } 
                    else
                    { 
                        // If its not a propertyinfo, methodinfo, or dependencyproperty, 
                        // all we know is that it must be an object...
                        propertyType = typeof(object); 
                        propertyCanWrite = false;
                    }
                }
#if !PBTCOMPILER 
            }
#endif 
        } 

 
        /// 
        /// Given an object that is either a PropertyInfo, MethodInfo for the static
        /// setter, or DependencyProperty, return the name of the property.  This assumes
        /// the Avalon rule that a DependencyProperty has a static getter "Get" + name. 
        /// 
        internal static string GetPropertyName(object propertyMember) 
        { 

#if !PBTCOMPILER 
            DependencyProperty dp = propertyMember as DependencyProperty;
            if (dp != null)
            {
                return dp.Name; 
            }
#endif 
 
            PropertyInfo propertyInfo = propertyMember as PropertyInfo;
            if (propertyInfo != null) 
            {
                return propertyInfo.Name;
            }
            else 
            {
                MethodInfo methodInfo = propertyMember as MethodInfo; 
                if (methodInfo != null) 
                {
                    return methodInfo.Name.Substring("Get".Length); 
                }
            }

            return null; 
        }
 
        ///  
        /// Given an object that is either a PropertyInfo, MethodInfo for the static
        /// setter, or DependencyProperty, return the type of the object that declares 
        /// or owns this property.
        /// 
        internal static Type GetDeclaringType(object propertyMember)
        { 
            Type validType = null;
            MemberInfo memInfo = propertyMember as MemberInfo; 
            if (memInfo != null) 
            {
                validType = memInfo.DeclaringType; 
            }
            else
            {
 
#if !PBTCOMPILER
                Debug.Assert( propertyMember is DependencyProperty); 
                validType = ((DependencyProperty)propertyMember).OwnerType; 
#endif
            } 

            return validType;
        }
#endregion Properties 

#region Types 
 
#if !PBTCOMPILER
        ///  
        ///  Return the type that corresponds to typeName, given that the type is
        ///  located as a subelement or property on the passed element.
        /// 
        ///  
        ///   The full xaml name of a type, including an xml namespace prefix, if needed.
        ///   The name is of the form prefix:typename, such as MyNs:MyNewButton 
        ///  
        /// 
        ///   A DependencyObject that is logical parent for the type to be resolved.  This 
        ///   is required because it is this element (or its ancestors) that contains
        ///   namespace mapping data that is needed to resolve the typeName.
        /// 
        ///  
        ///  The resolved clr type.  Null if not found
        ///  
        internal static Type GetTypeFromName(string typeName, DependencyObject element) 
        {
            if (element == null) 
            {
                throw new ArgumentNullException( "element" );
            }
            if (typeName == null) 
            {
                throw new ArgumentNullException( "typeName" ); 
            } 

            // Now map the prefix to an xml namespace uri 
            int colonIndex = typeName.IndexOf(':');
            string prefix = string.Empty;
            if (colonIndex > 0)
            { 
                prefix = typeName.Substring(0, colonIndex);
                typeName = typeName.Substring(colonIndex+1, typeName.Length-colonIndex-1); 
            } 

            // First, get the xmlns dictionary to map prefixes to xml namespace uris 
            XmlnsDictionary prefixDictionary = element.GetValue(XmlAttributeProperties.XmlnsDictionaryProperty)
                                               as XmlnsDictionary;

            object xmlNamespaceObject = (prefixDictionary != null) ? prefixDictionary[prefix] : null; 

            // Then get the list of NamespaceMapEntry objects that maps the xml namespace uri to one 
            // or more clr namespace / assembly pairs.  This should be stored on the root element 
            // of the tree.
            Hashtable namespaceMaps = element.GetValue(XmlAttributeProperties.XmlNamespaceMapsProperty) 
                                               as Hashtable;

            NamespaceMapEntry[] namespaces = (namespaceMaps != null && xmlNamespaceObject != null) ? namespaceMaps[xmlNamespaceObject] as NamespaceMapEntry[] : null;
 
            if (namespaces == null)
            { 
                // 

 


                if (prefix == string.Empty)
                { 
                    List namespaceAssemblyPair = GetClrNamespacePairFromCache(XamlReaderHelper.DefaultNamespaceURI);
                    foreach (ClrNamespaceAssemblyPair usd in namespaceAssemblyPair) 
                    { 
                        if (usd.AssemblyName != null)
                        { 
                            Assembly assy = ReflectionHelper.LoadAssembly(usd.AssemblyName, null);
                            if (assy != null)
                            {
                                string fullTypeName = String.Format(TypeConverterHelper.InvariantEnglishUS, "{0}.{1}", usd.ClrNamespace, typeName); 
                                Type t = assy.GetType(fullTypeName);
                                if (t != null) 
                                    return t; 
                            }
                        } 
                    }
                }

                // Stopgap didn't work, so fail now. 
                return null;
            } 
 
            // Check all the clr namespace / assembly pairs to see if there is a type
            // that matches the passed short name.  Return it if found. 
            for (int i = 0; i < namespaces.Length; i++)
            {
                Assembly assy = namespaces[i].Assembly;
                if (assy != null) 
                {
                    string fullTypeName = String.Format(TypeConverterHelper.InvariantEnglishUS, "{0}.{1}", namespaces[i].ClrNamespace, typeName); 
                    Type t = assy.GetType(fullTypeName); 
                    if (t != null)
                    { 
                        return t;
                    }
                }
            } 

            // Didn't find a match, so return null. 
            return null; 

       } 
#endif

        // Given a qualified member Name, returns its declaring Type and its name as a string.
        internal Type GetTargetTypeAndMember(string valueParam, 
                                             ParserContext context,
                                             bool isTypeExpected, 
                                         out string memberName) 
        {
            string typeName = valueParam; 
            string prefix = String.Empty;
            int typeIndex = typeName.IndexOf(':');
            if (typeIndex >= 0)
            { 
                prefix = typeName.Substring(0, typeIndex);
                typeName = typeName.Substring(typeIndex + 1); 
            } 

            memberName = null; 
            Type targetType = null;

            typeIndex = typeName.LastIndexOf('.');
            if (typeIndex >= 0) 
            {
                memberName = typeName.Substring(typeIndex + 1); 
                typeName = typeName.Substring(0, typeIndex); 
                string namespaceUri = context.XmlnsDictionary[prefix];
                TypeAndSerializer tas = GetTypeOnly(namespaceUri, typeName); 
                if (tas != null)
                {
                    targetType = tas.ObjectType;
                } 
                if (targetType == null)
                { 
                    ThrowException(SRID.ParserNoType, typeName); 
                }
            } 
            else if (!isTypeExpected && prefix.Length == 0)
            {
                // A Type may not be expected for e.g. for TemplateBinding param
                // values. In this case there must also not be a prefix. If there 
                // is one it will just point to a namespace and not a Type.
                memberName = typeName; 
            } 
            else
            { 
                // A type was expected but we didn't find one. So throw.
                ThrowException(SRID.ParserBadMemberReference, valueParam);
            }
 

            return targetType; 
        } 

        // Given a qualified member Name, returns its declaring Type and its name as a string. 
        internal Type GetDependencyPropertyOwnerAndName(string memberValue,
                                                        ParserContext context,
                                                        Type defaultTargetType,
                                                    out string memberName) 
        {
            Type targetType = GetTargetTypeAndMember(memberValue, context, false, out memberName); 
            if (targetType == null) 
            {
                targetType = defaultTargetType; 
                if (targetType == null)
                {
                    // if there was also no default target type then throw.
                    ThrowException(SRID.ParserBadMemberReference, memberValue); 
                }
            } 
 
            Debug.Assert(memberName != null);
            string fieldName = memberName + "Property"; 
            MemberInfo memberInfo = GetStaticMemberInfo(targetType, fieldName, true);
            Debug.Assert(memberInfo != null);

            // Need to get the actual type that declares the DP in order to 
            // correctly find a possible hit in the KnownProperties table.
            if (memberInfo.DeclaringType != targetType) 
            { 
                targetType = memberInfo.DeclaringType;
            } 

            return targetType;
        }
 
        // Gets the PropertyInfo or FieldInfo of a member.
        internal MemberInfo GetStaticMemberInfo(Type targetType, string memberName, bool fieldInfoOnly) 
        { 
            Debug.Assert(targetType != null);
            // first try public members only. 
            MemberInfo mi = GetStaticMemberInfo(targetType, memberName, fieldInfoOnly, false);

#if PBTCOMPILER
            if (mi == null) 
            {
                // If not found, then try non-public members next. 
                mi = GetStaticMemberInfo(targetType, memberName, fieldInfoOnly, true); 
                if (mi != null)
                { 
                    // if found, check access levels to see if it should really be allowed.
                    bool isAllowed = false;
                    PropertyInfo pi = mi as PropertyInfo;
                    if (pi != null) 
                    {
                        isAllowed = IsAllowedPropertyGet(pi, false); 
                    } 
                    else
                    { 
                        isAllowed = IsAllowedField(mi as FieldInfo);
                    }

                    if (!isAllowed) 
                    {
                        ThrowException(SRID.ParserStaticMemberNotAllowed, memberName, targetType.Name); 
                    } 
                }
            } 
#endif
            if (mi == null)
            {
                ThrowException(SRID.ParserInvalidStaticMember, memberName, targetType.Name); 
            }
 
            return mi; 
        }
 
        private MemberInfo GetStaticMemberInfo(Type targetType, string memberName, bool fieldInfoOnly, bool tryInternal)
        {
            MemberInfo memberInfo = null;
            BindingFlags bf = BindingFlags.Public | BindingFlags.FlattenHierarchy | BindingFlags.Static; 

            if (tryInternal) 
            { 
                bf |= BindingFlags.NonPublic;
            } 

            if (!fieldInfoOnly)
            {
                memberInfo = targetType.GetProperty(memberName, bf); 
            }
 
            if (memberInfo == null) 
            {
                memberInfo = targetType.GetField(memberName, bf); 
            }

            return memberInfo;
        } 

        ///  
        /// Get the Type that type corresponds to a localName in 
        /// the given namespace.  Note that localName can be of the form classname.typename,
        /// and can not include a namespace prefix. 
        /// 
        /// 
        /// Return the actual type and the serializer for that type as a
        /// TypeAndSerializer object from the cache.  Note that in this call 
        /// the Serializer information may not be present if a new TypeAndSerializer
        /// instance is created.  Be sure to check the IsSerializerTypeSet flag. 
        ///  
        internal TypeAndSerializer GetTypeOnly (
                string    xmlNamespace,     // xml namespace for the type 
                string    localName)        // local name of the type without any '.'
        {

            Debug.Assert(null != xmlNamespace,"null value passed for xmlNamespace"); 
            Debug.Assert(null != localName,"null value passed for localName");
 
            // check if object is in the Hash. 
            String hashString = xmlNamespace + ":" + localName;
 
            TypeAndSerializer typeAndSerializer =
                 _typeLookupFromXmlHashtable[hashString] as TypeAndSerializer;

            if (null == typeAndSerializer) 
            {
                if (!_typeLookupFromXmlHashtable.Contains(hashString)) 
                { 
                    typeAndSerializer = CreateTypeAndSerializer(xmlNamespace, localName);
                    _typeLookupFromXmlHashtable[hashString] = typeAndSerializer; 
                }
            }

            return typeAndSerializer; 
        }
 
        ///  
        /// Get the Type and serializer for that type corresponding to a localName in
        /// the given namespace.  Note that localName can be of the form classname.typename, 
        /// and can not include a namespace prefix.
        /// 
        /// 
        /// Return the actual type and the serializer for that type as a 
        /// TypeAndSerializer object from the cache.  If there is no
        /// serializer defined, as is the case for clr objects, then null is set 
        /// for the SerializerType in the returned TypeAndSerializer. Also if this type is 
        /// associated with a property we will check for serializer attributes on the property first.
        /// If no matching attribute is found for the property we resort to search for the attribute on the given type. 
        /// 
        internal TypeAndSerializer GetTypeAndSerializer (
                string    xmlNamespace,     // xml namespace for the type
                string    localName,        // local name of the type without any '.' 
                object    dpOrPiorMi)       // property associated with the type
        { 
 
            Debug.Assert(null != xmlNamespace,"null value passed for xmlNamespace");
            Debug.Assert(null != localName,"null value passed for localName"); 

            // check if object is in the Hash.
            String hashString = xmlNamespace + ":" + localName;
 
            TypeAndSerializer typeAndSerializer =
                _typeLookupFromXmlHashtable[hashString] as TypeAndSerializer; 
 
            if (null == typeAndSerializer)
            { 
                if (!_typeLookupFromXmlHashtable.Contains(hashString))
                {
                    typeAndSerializer = CreateTypeAndSerializer(xmlNamespace, localName);
                    _typeLookupFromXmlHashtable[hashString] = typeAndSerializer; 
                }
            } 
 
            // If we've found a TypeAndSerializer, check whether we have reflected for the
            // serializer information yet.  If not, then do it now. 
            if (typeAndSerializer != null && !typeAndSerializer.IsSerializerTypeSet)
            {
                // Check for SerializerAttribute on the type. The serializer for the type is evaluated
                // the very first time we create a new data strcuture for the given type. 
                typeAndSerializer.SerializerType = GetXamlSerializerForType(typeAndSerializer.ObjectType);
                typeAndSerializer.IsSerializerTypeSet = true; 
            } 

            return typeAndSerializer; 
        }

#if PBTCOMPILER
        private static bool IsFriendAssembly(Assembly assembly) 
        {
            // WinFx assemblies can never be friends of compiled assemblies, so just bail out. 
            if (assembly == XamlTypeMapper.AssemblyPF || 
                assembly == XamlTypeMapper.AssemblyPC ||
                assembly == XamlTypeMapper.AssemblyWB) 
            {
                return false;
            }
 
            return ReflectionHelper.IsFriendAssembly(assembly);
        } 
 
        private static bool IsInternalAllowedOnType(Type type)
        { 
            bool isInternalAllowed = ReflectionHelper.LocalAssemblyName == type.Assembly.GetName().Name ||
                                     IsFriendAssembly(type.Assembly);
            _hasInternals = _hasInternals || isInternalAllowed;
            return isInternalAllowed; 
        }
 
        private static bool IsInternalAllowedOnType(NamespaceMapEntry namespaceMap) 
        {
            bool isInternalAllowed = namespaceMap.LocalAssembly || IsFriendAssembly(namespaceMap.Assembly); 
            _hasInternals = _hasInternals || isInternalAllowed;
            return isInternalAllowed;
        }
 
        internal static bool HasInternals
        { 
            get { return _hasInternals; } 
            set { _hasInternals = value; }
        } 

        internal static bool HasLocalReference
        {
            get 
            {
                return _hasLocalReference; 
            } 
        }
#endif 

        /// 
        /// Create a TypeAndSerializer object for the passed data, if a valid Type
        /// is found. 
        /// 
        private TypeAndSerializer CreateTypeAndSerializer( 
                string    xmlNamespace,     // xml namespace for the type 
                string    localName)        // local name of the type without any '.'
        { 
            TypeAndSerializer typeAndSerializer = null;
            NamespaceMapEntry[] namespaceMaps = GetNamespaceMapEntries(xmlNamespace);

            if (namespaceMaps != null) 
            {
                // We'll do a first pass with only known types 
                // and then do a second pass with full reflection 
                bool knownTypesOnly = true;
                for (int count = 0; count < namespaceMaps.Length;) 
                {
                    NamespaceMapEntry namespaceMap = namespaceMaps[count];
                    if (null != namespaceMap)
                    { 
                        Type objectType = GetObjectType(namespaceMap, localName, knownTypesOnly);
                        if (null != objectType) 
                        { 
                            // A non-public type is never allowable, except for internal types
                            // in local or friend assemblies, so catch it here. 
                            if (!ReflectionHelper.IsPublicType(objectType))
                            {
#if PBTCOMPILER
                                // Don't allow internal known types in case we have any. 
                                if (knownTypesOnly ||
                                    !ReflectionHelper.IsInternalType(objectType) || 
                                    !IsInternalAllowedOnType(namespaceMap)) 
#else
                                // Give Full Trust callers a chance to resolve legitimate internal types. 
                                // This can be used by tools like designers and localizers running in FT.
                                if (!IsInternalTypeAllowedInFullTrust(objectType))
#endif
                                { 
                                    ThrowException(SRID.ParserPublicType, objectType.Name);
                                } 
                            } 
                            // Create new data structure to store information for the current type
                            typeAndSerializer = new TypeAndSerializer(); 
                            typeAndSerializer.ObjectType = objectType;

                            break;
                        } 
                    }
 
                    count++; 
                    if (knownTypesOnly && (count == namespaceMaps.Length))
                    { 
                        // Reset for second pass
                        knownTypesOnly = false;
                        count = 0;
                    } 
                }
            } 
            return typeAndSerializer; 
        }
 

        /// 
        /// Return the Type that corresponds to a localName within a given clr namespace
        /// in a given assembly 
        /// 
        /// Specifies the CLR namespace and Assembly to look in 
        /// The name of the type 
        /// Search only known types
        /// Type of object that corresponds to localName 
        private Type GetObjectType(
            NamespaceMapEntry namespaceMap,
            string            localName,
            bool              knownTypesOnly) 
        {
            Debug.Assert(namespaceMap.ClrNamespace != null,"Null CLR Namespace"); 
            Debug.Assert(localName != null,"Null localName"); 

            Type type = null; 

            // Construct the full type name by concatenating the clr namespace and the local name

            if (knownTypesOnly) 
            {
                short typeID = BamlMapTable.GetKnownTypeIdFromName(namespaceMap.AssemblyName, namespaceMap.ClrNamespace, localName); 
                if (typeID != 0) 
                {
                    type = BamlMapTable.GetKnownTypeFromId(typeID); 
                }
            }
            else
            { 
               Assembly assembly ;
#if PBTCOMPILER 
                try 
                {
#endif 
                    // This may not work if the assembly is not present at compile time, so allow for that.
                    // At runtime it had better be there, so don't ignore it.
                    assembly = namespaceMap.Assembly;
#if PBTCOMPILER 
                }
                catch (FileNotFoundException) 
                { 
                    assembly = null;
                } 
#endif

                if (null != assembly)
                { 
                    // Type loads may fail if all the prerequisite assemblies haven't been loaded
                    // yet.  In this case, try one more time after loaded all assemblies that the 
                    // compiler may have told the XamlTypeMapper about. 
                    string fullTypeName = namespaceMap.ClrNamespace + "." + localName;
                    try 
                    {
                        type = assembly.GetType(fullTypeName);

                    } 
                    catch (Exception e)
                    { 
                        if (CriticalExceptions.IsCriticalException(e)) 
                        {
                           throw; 
                        }
                        else
                        {
                            if (LoadReferenceAssemblies()) 
                            {
                                try 
                                { 
                                    type = assembly.GetType(fullTypeName);
                                } 
                                catch (ArgumentException)
                                {
                                    // A null type is allowable, and the caller will catch it
                                    type = null; 
                                }
                            } 
                        } 
                    }
                } 
            }

            return type;
        } 

        internal int GetCustomBamlSerializerIdForType(Type objectType) 
        { 
            // support for xaml -> custom binary and custom binary -> object.
            if (objectType == KnownTypes.Types[(int)KnownElements.Brush]) 
            {
                return (int)KnownElements.XamlBrushSerializer;
            }
            else if (objectType == KnownTypes.Types[(int)KnownElements.Geometry] || 
                     objectType == KnownTypes.Types[(int)KnownElements.StreamGeometry])
            { 
                // 
                // The only type of geometry that can be serialized to a string is
                // a StreamGeometry, so if objectType is Geometry and we're getting here 
                // then the attribute must in fact be a StreamGeometry.
                //
                return (int)KnownElements.XamlPathDataSerializer;
            } 
            else if (objectType == KnownTypes.Types[(int)KnownElements.Point3DCollection])
            { 
                return (int)KnownElements.XamlPoint3DCollectionSerializer; 
            }
            else if (objectType == KnownTypes.Types[(int)KnownElements.Vector3DCollection]) 
            {
                return (int)KnownElements.XamlVector3DCollectionSerializer;
            }
            else if (objectType == KnownTypes.Types[(int)KnownElements.PointCollection]) 
            {
                return (int)KnownElements.XamlPointCollectionSerializer; 
            } 
            else if (objectType == KnownTypes.Types[(int)KnownElements.Int32Collection])
            { 
                return (int)KnownElements.XamlInt32CollectionSerializer;
            }

            return 0; 
        }
 
        ///  
        /// Sees if type has a Xaml serializer attribute that gives the
        /// type name of the serializer and figure out the type. 
        /// 
        internal Type GetXamlSerializerForType(Type objectType)
        {
            // support for xaml -> baml and baml -> objects 
            if (objectType == KnownTypes.Types[(int)KnownElements.Style])
            { 
                return typeof(XamlStyleSerializer); 
            }
            else if (KnownTypes.Types[(int)KnownElements.FrameworkTemplate].IsAssignableFrom(objectType)) 
            {
                return typeof(XamlTemplateSerializer);
            }
 
            return null;
        } 
 
#if !PBTCOMPILER
        internal static Type GetInternalTypeHelperTypeFromAssembly(ParserContext pc) 
        {
            Assembly a = pc.StreamCreatedAssembly;
            if (a == null)
            { 
                return null;
            } 
 
            Type ithType = a.GetType(GeneratedNamespace + "." + GeneratedInternalTypeHelperClassName);
            if (ithType == null) 
            {
                // if GITH is not found, try to see if a root namespace was implicitly added to it.
                // This would be the case for assemblies built with VB that had a RootNamespace
                // property specified in the project file. 
                RootNamespaceAttribute rnsa = (RootNamespaceAttribute)Attribute.GetCustomAttribute(a, typeof(RootNamespaceAttribute));
                if (rnsa != null) 
                { 
                    string rootNamespace = rnsa.Namespace;
                    ithType = a.GetType(rootNamespace + "." + GeneratedNamespace + "." + GeneratedInternalTypeHelperClassName); 
                }
            }

            return ithType; 
        }
 
        private static InternalTypeHelper GetInternalTypeHelperFromAssembly(ParserContext pc) 
        {
            InternalTypeHelper ith = null; 
            Type ithType = GetInternalTypeHelperTypeFromAssembly(pc);
            if (ithType != null)
            {
                ith = (InternalTypeHelper)Activator.CreateInstance(ithType); 
            }
            return ith; 
        } 

        ///  
        /// This function needs to demand reflection permission in order to create instances of
        /// allowed\accessible internal types. If permission is granted, the parser will directly
        /// use reflection to create the internal instance. If not, it will call a method on a
        /// generated class in the user's code context in order to attempt creating the internal 
        /// instance using the user app's security context.
        ///  
        internal static object CreateInternalInstance(ParserContext pc, Type type) 
        {
            object instance = null; 
            // if caller has member access reflection permission, use reflection directly
            if (SecurityHelper.CallerHasMemberAccessReflectionPermission())
            {
                instance = Activator.CreateInstance(type, 
                                                    BindingFlags.Public |
                                                    BindingFlags.NonPublic | 
                                                    BindingFlags.Instance | 
                                                    BindingFlags.CreateInstance,
                                                    null, 
                                                    null,
                                                    TypeConverterHelper.InvariantEnglishUS);
            }
            else 
            {
                // else this must be an accessible internal type in PT --- call the generated InternalTypeHelper 
                // in the caller's secuirty context. 

                // In this case pc.StreamCreatedAssembly is guaranteed to be the assembly from which the current 
                // stream being read was created from. So even if the internal type were not legitimate, the call
                // to create it via ith.CreateInstance would fail in PT.
                InternalTypeHelper ith = XamlTypeMapper.GetInternalTypeHelperFromAssembly(pc);
                if (ith != null) 
                {
                    instance = ith.CreateInstance(type, TypeConverterHelper.InvariantEnglishUS); 
                } 
            }
 
            return instance;
        }

        ///  
        /// This function needs to demand reflection permission in order to get an allowed\accessible
        /// internal property value on an allowed\accessible type. If permission is granted, the parser 
        /// will directly use reflection to get the property value. If not, it will call a method on a 
        /// generated class in the user's code context in order to attempt getting the internal property
        /// value using the user app's security context. 
        /// 
        internal static object GetInternalPropertyValue(ParserContext pc, object rootElement, PropertyInfo pi, object target)
        {
            object propValue = null; 
            bool isPublicProperty = false;
            bool allowProtected = (rootElement is IComponentConnector) && (rootElement == target); 
            bool isAllowedProperty = IsAllowedPropertyGet(pi, allowProtected, out isPublicProperty); 

            if (isAllowedProperty) 
            {
                // if public getter on internal type or caller has member access permission, use reflection directly
                if (isPublicProperty || SecurityHelper.CallerHasMemberAccessReflectionPermission())
                { 
                    propValue = pi.GetValue(target, BindingFlags.Default, null, null, TypeConverterHelper.InvariantEnglishUS);
                } 
                else 
                {
                    // else this must be an internal property getter on an accessible internal or public type --- call 
                    // the generated helper in caller's secuirty context.

                    // In this case pc.StreamCreatedAssembly is guaranteed to be the assembly from which the current stream
                    // being read was created from. So even if the internal property were not legitimate, the call 
                    // to access it via ith.GetPropertyValue would fail in PT.
                    InternalTypeHelper ith = GetInternalTypeHelperFromAssembly(pc); 
                    if (ith != null) 
                    {
                        propValue = ith.GetPropertyValue(pi, target, TypeConverterHelper.InvariantEnglishUS); 
                    }
                }
            }
 
            return propValue;
        } 
 
        /// 
        /// This function needs to demand reflection permission in order to set an allowed\accessible internal 
        /// property value on an allowed\accessible type. If permission is granted, the parser will directly use
        /// reflection to set the property value. If not, it will call a method on a generated class in the user's
        /// code context in order to attempt setting the internal property value using the user app's security context.
        ///  
        internal static bool SetInternalPropertyValue(ParserContext pc, object rootElement, PropertyInfo pi, object target, object value)
        { 
            bool isPublicProperty = false; 
            bool allowProtected = (rootElement is IComponentConnector) && (rootElement == target);
            bool isAllowedProperty = IsAllowedPropertySet(pi, allowProtected, out isPublicProperty); 

            if (isAllowedProperty)
            {
                // if public setter on internal type or caller has member access permission, use reflection directly 
                if (isPublicProperty || SecurityHelper.CallerHasMemberAccessReflectionPermission())
                { 
                    pi.SetValue(target, value, BindingFlags.Default, null, null, TypeConverterHelper.InvariantEnglishUS); 
                    return true;
                } 
                else
                {
                    // else this must be an internal property setter on an accessible internal or public type --- call
                    // the generated helper in caller's secuirty context. 

                    // In this case pc.StreamCreatedAssembly is guaranteed to be the assembly from which the current stream 
                    // being read was created from. So even if the internal property were not legitimate, the call 
                    // to set it via ith.SetPropertyValue would fail in PT.
                    InternalTypeHelper ith = GetInternalTypeHelperFromAssembly(pc); 
                    if (ith != null)
                    {
                        ith.SetPropertyValue(pi, target, value, TypeConverterHelper.InvariantEnglishUS);
                        return true; 
                    }
                } 
            } 

            return false; 
        }

        /// 
        /// This function needs to demand reflection permission in order to create an accessible delegate for a 
        /// non public event handler method. If permission is granted, the parser will directly use reflection
        /// to create the delegate. If not, it will call a method on a generated class in the user's code context 
        /// in order to attempt creating the delegate using the user app's security context. 
        /// 
        internal static Delegate CreateDelegate(ParserContext pc, Type delegateType, object target, string handler) 
        {
            Delegate d = null;
            bool isAllowedDelegateType = ReflectionHelper.IsPublicType(delegateType) || ReflectionHelper.IsInternalType(delegateType);
 
            if (isAllowedDelegateType)
            { 
                if (SecurityHelper.CallerHasMemberAccessReflectionPermission()) 
                {
                    d = Delegate.CreateDelegate(delegateType, target, handler); 
                }
                else
                {
                    // target is always the root generated element. Check to see if it is in the 
                    // same assembly as the one from which the currently processed stream was created,
                    // as an added precaution. 
                    if (target.GetType().Assembly == pc.StreamCreatedAssembly) 
                    {
                        InternalTypeHelper ith = GetInternalTypeHelperFromAssembly(pc); 
                        if (ith != null)
                        {
                            d = ith.CreateDelegate(delegateType, target, handler);
                        } 
                    }
                } 
            } 

            return d; 
        }

        /// 
        /// This function needs to demand reflection permission in order to add a delegate handler for an 
        /// allowed\accessible internal event on an allowed\accessible type. If permission is granted, the
        /// parser will directly use reflection to add the event handler delegate. If not, it will call a 
        /// method on a generated class in the user's code context in order to attempt adding the internal 
        /// event handler delegate using the user app's security context.
        ///  
        internal static bool AddInternalEventHandler(ParserContext pc, object rootElement, EventInfo eventInfo, object target, Delegate handler)
        {
            bool isPublicEvent = false;
            bool allowProtected = rootElement == target; 
            bool isAllowedEvent = IsAllowedEvent(eventInfo, allowProtected, out isPublicEvent);
 
            if (isAllowedEvent) 
            {
                // if public event on internal type or caller has member access permission, use reflection directly 
                if (isPublicEvent || SecurityHelper.CallerHasMemberAccessReflectionPermission())
                {
                    eventInfo.AddEventHandler(target, handler);
                    return true; 
                }
                else 
                { 
                    // else this must be an internal event on an accessible internal or public type --- call
                    // the generated helper in caller's secuirty context. 

                    // In this case pc.StreamCreatedAssembly is guaranteed to be the assembly from which the current
                    // stream being read was created from. So even if the internal event ere not legitimate, the call
                    // to add a handler to it via ith.AddEventHandler would fail in PT. 
                    InternalTypeHelper ith = GetInternalTypeHelperFromAssembly(pc);
                    if (ith != null) 
                    { 
                        ith.AddEventHandler(eventInfo, target, handler);
                        return true; 
                    }
                }
            }
 
            return false;
        } 
#endif 

        // Return true if this is a locally compiled assembly 
        internal bool IsLocalAssembly(string namespaceUri)
        {
            bool localAssembly = false;
#if PBTCOMPILER 
            NamespaceMapEntry[] namespaceMaps = GetNamespaceMapEntries(namespaceUri);
            localAssembly = (namespaceMaps != null && namespaceMaps.Length == 1 && namespaceMaps[0].LocalAssembly); 
#endif 
            return localAssembly;
        } 

        /// 
        /// Given a string of the format MyNs:MyButton return the type that it refers to.  This uses
        /// the XmlnsDictionary in the passed parse context to resolve prefixes on the 
        /// type names
        ///  
        internal Type GetTypeFromBaseString( 
            string        typeString,
            ParserContext context, 
            bool          throwOnError)
        {
            string xmlns = string.Empty;
            Type keyObject = null; 
            // Check if the typeString is of the form xmlns:type.  If so, get
            // the appropriate mapped NamespaceURI.  If not, use the default URI 
            int colonIndex = typeString.IndexOf(':'); 
            if (colonIndex == -1)
            { 
                xmlns = context.XmlnsDictionary[string.Empty];
                if (xmlns == null)
                {
                    ThrowException(SRID.ParserUndeclaredNS, string.Empty); 
                }
            } 
            else 
            {
                string prefix = typeString.Substring(0, colonIndex); 
                xmlns = context.XmlnsDictionary[prefix];
                if (xmlns == null)
                {
                    ThrowException(SRID.ParserUndeclaredNS, prefix); 
                }
                else 
                { 
                    typeString = typeString.Substring(colonIndex + 1);
                } 
            }

#if !PBTCOMPILER
            // Optimize for SystemMetric types that are very frequently used. 
            if (string.CompareOrdinal(xmlns, XamlReaderHelper.DefaultNamespaceURI) == 0)
            { 
                switch (typeString) 
                {
                    case "SystemParameters": 
                        keyObject = typeof(SystemParameters);
                        break;

                    case "SystemColors": 
                        keyObject = typeof(SystemColors);
                        break; 
 
                    case "SystemFonts":
                        keyObject = typeof(SystemFonts); 
                        break;
                }
            }
#endif 
            if (keyObject == null)
            { 
                keyObject = GetType(xmlns, typeString); 
            }
 
            if (keyObject == null && throwOnError)
            {
                // if local type, then don't throw as it may be resolved in pass2.
                // it is upto the caller who has context about compilation passes 
                // to throw as appropriate in Pass2 if the type is still not found.
                if (!IsLocalAssembly(xmlns)) 
                { 
                    _lineNumber = context != null ? context.LineNumber : 0;
                    _linePosition = context != null ? context.LinePosition : 0; 

                    ThrowException(SRID.ParserResourceKeyType, typeString);
                }
            } 

            return keyObject; 
        } 

#if PBTCOMPILER 
        internal Type GetTypeArgsType(
            string typeString,
            ParserContext context,
            out string localTypeArgClassName, 
            out string localTypeArgNamespace)
        { 
            Type t = null; 
            localTypeArgClassName = string.Empty;
            localTypeArgNamespace = string.Empty; 

            // Check if the typeString is of the form xmlns:type.  If so, get
            // the appropriate mapped NamespaceURI.  If not, use the default URI
            int colonIndex = typeString.IndexOf(':'); 
            if (colonIndex == -1)
            { 
                string xmlns = context.XmlnsDictionary[string.Empty]; 
                if (xmlns == null)
                { 
                    ThrowException(SRID.ParserUndeclaredNS, string.Empty);
                }
                else
                { 
                    t = GetType(xmlns, typeString);
                } 
            } 
            else
            { 
                string prefix = typeString.Substring(0, colonIndex);
                string xmlns = context.XmlnsDictionary[prefix];
                if (xmlns == null)
                { 
                    ThrowException(SRID.ParserUndeclaredNS, prefix);
                } 
                else 
                {
                    NamespaceMapEntry[] namespaceMaps = GetNamespaceMapEntries(xmlns); 
                    typeString = typeString.Substring(colonIndex + 1);
                    bool isLocalArg = namespaceMaps != null &&
                                      namespaceMaps.Length == 1 &&
                                      namespaceMaps[0].LocalAssembly; 

                    if (isLocalArg) 
                    { 
                        localTypeArgNamespace = namespaceMaps[0].ClrNamespace;
                        localTypeArgClassName = typeString; 
                    }
                    else
                    {
                        t = GetType(xmlns, typeString); 
                    }
                } 
            } 

            return t; 
        }
#endif

        ///  
        /// Helper method given a type returns the Cached information for the type.  If there
        /// is no existing cached information for that type, a new cache object is created 
        /// and added to the cache. 
        /// 
        private TypeInformationCacheData GetCachedInformationForType(Type type) 
        {
            TypeInformationCacheData typeInformationCacheData;
            typeInformationCacheData = _typeInformationCache[type] as TypeInformationCacheData;
            if (null == typeInformationCacheData) 
            {
                typeInformationCacheData = new TypeInformationCacheData(type.BaseType); 
                typeInformationCacheData.ClrNamespace = type.Namespace; 

                _typeInformationCache[type] = typeInformationCacheData; 
            }

            return typeInformationCacheData;
        } 

#if !PBTCOMPILER 
 
        /// 
        /// Returns the type's BaseType. This is cached because the .net Type.BaseType() 
        /// call is expensive.
        /// 
        private Type GetCachedBaseType(Type t)
        { 
            TypeInformationCacheData typeInformation = GetCachedInformationForType(t);
 
            return typeInformation.BaseType; 
        }
 
        /***************************************************************************\
        *
        * XamlTypeMapper.ProcessNameString
        * 
        * Given a name in markup, extract and process the prefix if any.
        * 
        \***************************************************************************/ 

        internal static string ProcessNameString(ParserContext parserContext, ref string nameString) 
        {
            // For certain parts of the styling markup, a property is specified as an
            //  attribute value.  This may include the namespace specification.  Normally
            //  when we encounter this in an attribute the XML parser processes the name- 
            //  space for us.  But when it's the value we'll have to deal with it our-
            //  selves.  Look for the namespace specifier and extract it for namespace lookup. 
            //  "foons:BarClass.BazProp" -> "http://www.example.com" + "BarClass.BazProp" 

            // The colon is what we look for to determine if there's a namespace prefix specifier. 
            int nsIndex = nameString.IndexOf(':');
            string nsPrefix = string.Empty;
            if( nsIndex != -1 )
            { 
                // Found a namespace prefix separator, so create replacement propertyName.
                // String processing - split "foons" from "BarClass.BazProp" 
                nsPrefix = nameString.Substring (0, nsIndex); 
                nameString = nameString.Substring (nsIndex + 1);
            } 

            // Find the namespace, even if its the default one
            string namespaceURI = parserContext.XmlnsDictionary[nsPrefix];
            if (namespaceURI == null) 
            {
                parserContext.XamlTypeMapper.ThrowException(SRID.ParserPrefixNSProperty, nsPrefix, nameString); 
            } 

            return namespaceURI; 
        }

        /***************************************************************************\
        * 
        * XamlTypeMapper.ParsePropertyName
        * 
        * Given a property name, find the associated DependencyProperty and return it. 
        *
        \***************************************************************************/ 

        internal static DependencyProperty ParsePropertyName(
                ParserContext   parserContext,
                string          propertyName, 
            ref Type            ownerType)
        { 
            string namespaceURI = ProcessNameString(parserContext, ref propertyName); 

            DependencyProperty dp = parserContext.XamlTypeMapper.DependencyPropertyFromName( 
                                            propertyName,
                                            namespaceURI,
                                            ref ownerType);
 
            return dp;
        } 
 
        /****************************************************************************\
        * 
        * XamlTypeMapper.ParseEventName
        *
        * Given an event name, find the associated RoutedEvent and return it.
        * 
        \***************************************************************************/
 
        internal static RoutedEvent ParseEventName( 
            ParserContext   parserContext,
            string          eventName, 
            Type            ownerType)
        {
            string namespaceURI = ProcessNameString(parserContext, ref eventName);
 
            RoutedEvent Event = parserContext.XamlTypeMapper.GetRoutedEvent(
                ownerType, namespaceURI, eventName); 
 
            return Event;
        } 

#endif

        ///  
        /// Return an object of the passed type.
        ///  
        ///  
        /// If the type is a KnownElement (which it likely will be) it is faster
        /// to create it using the KnownTypes hardcoded constructors, so check that 
        /// first before using the Activator.CreateInstance fallback.
        /// 
        internal object CreateInstance(Type t)
        { 
            object o = null;
#if !PBTCOMPILER 
            short typeId = BamlMapTable.GetKnownTypeIdFromType(t); 
            if (typeId < 0)
            { 
                o = MapTable.CreateKnownTypeFromId(typeId);
            }
            else
            { 
#endif
                o = Activator.CreateInstance(t, 
                                             BindingFlags.Instance | BindingFlags.CreateInstance | BindingFlags.Public, 
                                             null,
                                             null, 
                                             TypeConverterHelper.InvariantEnglishUS);
#if !PBTCOMPILER
            }
#endif 
            return o;
        } 
 
#endregion Types
 
#region Namespaces

        // Return true if the passed namespace is known, meaning that it maps
        // to a set of assemblies and clr namespaces 
        internal bool IsXmlNamespaceKnown(
                string xmlNamespace, 
            out string newXmlNamespace) 
        {
            bool result; 

            // if the namespace is empty, then there's no need to do all the extra work associated with getting the
            // namespace map entries.  Just return false.
            if (String.IsNullOrEmpty(xmlNamespace)) 
            {
                result = false; 
                newXmlNamespace = null; 
            }
            else 
            {
                NamespaceMapEntry[] namespaceMaps = GetNamespaceMapEntries(xmlNamespace);
                if (_xmlnsCache == null)
                { 
#if PBTCOMPILER
                    Debug.Assert(false, "Should initialize cache prior to compiling"); 
#else 
                    _xmlnsCache = new XmlnsCache();
#endif 
                }
                newXmlNamespace = _xmlnsCache.GetNewXmlnamespace(xmlNamespace);

                // if the xmlNamespace has valid entries or is mapped to another namespace, then it is known. 
                result = (namespaceMaps != null && namespaceMaps.Length > 0) ||
                              !String.IsNullOrEmpty(newXmlNamespace); 
            } 

            return result; // return variable isn't needed, just makes debugging easier. 
        }


#if !PBTCOMPILER 

        // 
        // Pass xmlNamespace to AssemblyList mapping to xmlnsCache so that the xmlnsCache 
        // can take the assembly list to get the right xmlns->clrns mapping later.
        // 
        internal void SetUriToAssemblyNameMapping(string xmlNamespace, short[] assemblyIds)
        {
            //
            // If the xmlNamespace is for a mapping,  there is no need to ask for xmlnsCache 
            // to get xmlns->clrns mapping.
            // 
            if (xmlNamespace.StartsWith(XamlReaderHelper.MappingProtocol, StringComparison.Ordinal)) 
            {
                return; 
            }

            if (_xmlnsCache == null)
            { 
                _xmlnsCache = new XmlnsCache();
            } 
 
            string[] asmNameList = null;
 
            if (assemblyIds != null && assemblyIds.Length > 0)
            {
                asmNameList = new string[assemblyIds.Length];
 
                for (int i = 0; i < assemblyIds.Length; i++)
                { 
                    BamlAssemblyInfoRecord assemblyInfo = MapTable.GetAssemblyInfoFromId(assemblyIds[i]); 
                    asmNameList[i] = assemblyInfo.AssemblyFullName;
                } 
            }

            _xmlnsCache.SetUriToAssemblyNameMapping(xmlNamespace, asmNameList);
        } 

 
#endif 

        /// 
        /// Returns a NamespaceMapEntry array given a xmlNamespace.  Each
        /// NamespaceMapEntry contains information the XamlTypeMapper uses for Mapping between an xml
        /// XmlNamespace and what Assembly, Namespace to look in.
        /// 
        ///
        /// The xmlNamespace for the Map 
        /// 
        ///
        /// Returns an Array of NamespaceMapEntry 
        ///
        internal NamespaceMapEntry[] GetNamespaceMapEntries(string xmlNamespace)
        {
            NamespaceMapEntry[] namespaceMaps = null; 

            // check out hash and if already have resolved the Uri 
            // don't resolve again. 
            namespaceMaps = _namespaceMapHashList[xmlNamespace] as NamespaceMapEntry[];
 
            if (null == namespaceMaps)
            {
                ArrayList namespaceMapArray = new ArrayList(6);
 
                // this is the first time the XmlNamespace has been requested
                // add items from the namespaceMap and then walk the assembly 
                // list to find matching items. 

                if (null != _namespaceMaps) 
                {
                    // need to find out the total number of entries by asking each hash
                    // review, may be better to sort these firt time through
                    // assumption here that the namespaceMap entries are small. 
                    for (int i = 0; i < _namespaceMaps.Length; i++)
                    { 
                        NamespaceMapEntry namespaceMap = _namespaceMaps[i]; 

                        if (namespaceMap.XmlNamespace == xmlNamespace) 
                        {
                            namespaceMapArray.Add(namespaceMap);
                        }
                    } 
                }
 
 
                List namespaceAssemblyPair;
                // Check for Processing instructions for mapping.  If that fails, 
                // check for Xmlns definition files.
                if (PITable.Contains(xmlNamespace))
                {
                    namespaceAssemblyPair = new List(1); 
                    namespaceAssemblyPair.Add((ClrNamespaceAssemblyPair)PITable[xmlNamespace]);
                } 
                else 
                {
                    namespaceAssemblyPair = GetClrNamespacePairFromCache(xmlNamespace); 
                }

                // now walk through any using statements we got and add them
                if (null != namespaceAssemblyPair) 
                {
 
                    for (int j = 0; j < namespaceAssemblyPair.Count; j++) 
                    {
                        ClrNamespaceAssemblyPair mapping = namespaceAssemblyPair[j]; 
                        string          usingAssemblyName = null;
                        string          path =  AssemblyPathFor(mapping.AssemblyName);

                        // using could either have an assembly or not, if it does 
                        // have an assembly just need to add this one entry, if
                        // no assembly map in the referenced assemblies. 
 
                        if (
#if PBTCOMPILER 
                            mapping.LocalAssembly ||
#endif
                            (!(String.IsNullOrEmpty(mapping.AssemblyName)) && !(String.IsNullOrEmpty(mapping.ClrNamespace))) )
                        { 
                            usingAssemblyName = mapping.AssemblyName;
                            NamespaceMapEntry nsMap = new NamespaceMapEntry(xmlNamespace, 
                                usingAssemblyName,mapping.ClrNamespace,path); 

#if PBTCOMPILER 
                            nsMap.LocalAssembly = mapping.LocalAssembly;
                            // if xaml has local components, then it could have internals
                            // but there is no way to determine this until pass2. But we
                            // need to set this here in order to generate the InternalTypeHelper 
                            // in pass1.
                            if (nsMap.LocalAssembly) 
                            { 
                                _hasLocalReference = true;
                            } 
#endif

                            namespaceMapArray.Add(nsMap);
                        } 

                        if (!String.IsNullOrEmpty(mapping.ClrNamespace)) 
                        { 
                            // Also add in any assembly from the AssemblyNames collection
                            for (int k = 0; k < _assemblyNames.Length; k++) 
                            {
                                if (usingAssemblyName == null)
                                {
                                    namespaceMapArray.Add(new NamespaceMapEntry(xmlNamespace, 
                                                      _assemblyNames[k],
                                                      mapping.ClrNamespace, 
                                                      path)); 
                                }
                                else 
                                {
                                    // If we have a using Assembly, then only add assemblies from
                                    // AssemblyNames that match the using Assembly.
                                    int charIndex = _assemblyNames[k].LastIndexOf('\\'); 
                                    if (charIndex > 0 &&
                                        _assemblyNames[k].Substring(charIndex + 1) == usingAssemblyName) 
                                    { 
                                        namespaceMapArray.Add(new NamespaceMapEntry(xmlNamespace,
                                                        _assemblyNames[k], 
                                                        mapping.ClrNamespace,
                                                        path));
                                    }
                                } 
                            }
                        } 
                    } 
                }
 
                // convert to a namespaceMap
                namespaceMaps = (NamespaceMapEntry[]) namespaceMapArray.ToArray(typeof(NamespaceMapEntry));

                // add to hash even if not items so we don't do this work again. 
                if (null != namespaceMaps)
                { 
                    _namespaceMapHashList.Add(xmlNamespace,namespaceMaps); 
                }
            } 

            return namespaceMaps;
        }
 

#if PBTCOMPILER 
 
        /// 
        /// Invalide the namespace mapping cache associated with a namespace. This should be done 
        /// when the PITable has been changed and the mapping cache might have been built for the
        /// namespace already.
        /// 
        /// The namespace to for whose cache to invalidate 
        internal void InvalidateMappingCache(string xmlNamespace)
        { 
            _namespaceMapHashList.Remove(xmlNamespace); 
        }
 
        /// 
        /// Set up the XmlnsCache use for resolving namespaces to use only the assembly path
        /// table that has been built up by the XamlTypeMapper.
        ///  
        internal void InitializeReferenceXmlnsCache()
        { 
            _xmlnsCache = new XmlnsCache(_assemblyPathTable); 
        }
 
#else
        // Get the xml namespace from the _piReverseTable that corresponds to the
        // passed type full name and assembly name
        internal string GetXmlNamespace( 
            string  clrNamespaceFullName,
            string  assemblyFullName) 
        { 
            string upperAssemblyName = assemblyFullName.ToUpper(
                                              TypeConverterHelper.InvariantEnglishUS); 

            String fullName = clrNamespaceFullName + "#" + upperAssemblyName;

            String ret; 

            if (_piReverseTable.TryGetValue(fullName, out ret) && ret != null) 
            { 
                return ret;
            } 
            else
            {
               return string.Empty;
            } 
        }
 
        ///  
        /// Given a Type returns it's .net Namespace. This is cached because each call
        /// to .urtNamspace allocates a string. 
        /// 
        private string GetCachedNamespace(Type t)
        {
            TypeInformationCacheData typeInformation = GetCachedInformationForType(t); 

            return typeInformation.ClrNamespace; 
        } 
#endif
 
        /// 
        /// Check an Xml namespace URI and loads the associated Clr namespaces and assemblies
        /// into ClrNamespaceAssemblyPair structures.
        ///  Throws an exception if no valid namespaces are found. 
        /// 
        /// Xml namespace that maps to one or more Clr namespace 
        /// and assembly pairs 
        /// array of ClrNamespaceAssemblyPair structures
        internal static List GetClrNamespacePairFromCache( 
                string namespaceUri)
        {

            List mappingArray = null; 

            // 
 

 
            if (_xmlnsCache == null)
            {
#if PBTCOMPILER
                Debug.Assert(false, "Should initialize cache prior to compiling"); 
#else
                _xmlnsCache = new XmlnsCache(); 
#endif 
            }
 
            mappingArray = _xmlnsCache.GetMappingArray(namespaceUri);

            return mappingArray;
        } 

#endregion Namespaces 
 
#region TypeConverters
 
        // Returns the Type of the TypeConverter for the given type.
        // Returns null if not found.
        internal Type GetTypeConverterType(Type type)
        { 
            Debug.Assert(null != type, "Null passed for type to GetTypeConverterType");
            TypeInformationCacheData typeData = GetCachedInformationForType(type) as TypeInformationCacheData; 
            Type converterType = null; 

            if (null != typeData.TypeConverterType) 
            {
                converterType = typeData.TypeConverterType;
                return converterType;
            } 

            // Check for known TypeConverters first. These are always public. 
            converterType = MapTable.GetKnownConverterTypeFromType(type); 
            if (converterType == null)
            { 
                // If not found, next try looking for the TypeConverter for the type using reflection.
                converterType = TypeConverterHelper.GetConverterType(type);
                if (converterType == null)
                { 
                    converterType = TypeConverterHelper.GetCoreConverterTypeFromCustomType(type);
                } 
            } 

            typeData.TypeConverterType = converterType; 
            return converterType;
        }

#if !PBTCOMPILER 
        // Returns the TypeConverter for the given type
        // Throws a XamlParseException if no TypeConverter is found. 
        internal TypeConverter GetTypeConverter(Type type) 
        {
            Debug.Assert(null != type, "Null passed for type to GetTypeConverter"); 

            TypeInformationCacheData typeData = GetCachedInformationForType(type) as TypeInformationCacheData;
            TypeConverter typeConverter = null;
 
            // if the TypeConverter for this type was ever successfully
            // queried before it should have a non-null value. 
            if (null != typeData.Converter) 
            {
                typeConverter = typeData.Converter; 
                return typeConverter;
            }

            // Check for known TypeConverters first. These are always public. 
            typeConverter = MapTable.GetKnownConverterFromType(type);
            if (typeConverter == null) 
            { 
                // If not found, next try looking for the TypeConverter for the type using reflection.
                Type converterType = TypeConverterHelper.GetConverterType(type); 
                if (converterType == null)
                {
                    typeConverter = TypeConverterHelper.GetCoreConverterFromCustomType(type);
                } 
                else
                { 
                    typeConverter = CreateInstance(converterType) as TypeConverter; 
                }
            } 

            typeData.Converter = typeConverter;

            if (null == typeConverter) 
            {
                ThrowException(SRID.ParserNoTypeConv, type.Name); 
            } 

            return typeConverter; 
        }
#endif

        // Returns the Type of the TypeConverter applied to the given property itself. 
        // Returns null if not found.
        internal Type GetPropertyConverterType(Type propType, object dpOrPiOrMi) 
        { 
            Debug.Assert(null != propType, "Null passed for propType to GetPropertyConverterType");
            Type converterType = null; 

            // If the current value being parsed is a property value then we must look
            // if there is special TypeConverter specified as attribute for this property
            if (null != dpOrPiOrMi) 
            {
#if PBTCOMPILER 
                TypeInformationCacheData typeData = GetCachedInformationForType(propType) as TypeInformationCacheData; 
                object ret = typeData.PropertyConverters[dpOrPiOrMi];
                if (null != ret) 
                {
                    converterType = (Type)ret;
                    return converterType;
                } 
                else
#endif 
                { 
                    // Get the memberInfo from the DP, PropertyInfo(CLR) or MethodInfo(Attached) for the property
                    MemberInfo memberInfo = TypeConverterHelper.GetMemberInfoForPropertyConverter(dpOrPiOrMi); 
                    if (memberInfo != null)
                    {
                        // If not found, next try looking for the TypeConverter on the property itself using reflection.
                        converterType = TypeConverterHelper.GetConverterType(memberInfo); 
                    }
                } 
 
#if PBTCOMPILER
                // Cache the per property TypeConverter type. This doesn't need to be cached at run-time 
                // since GetPropertyConverter will be used for getting the actual TypeConveretr instance.
                // This saves us the cost of a HashTable.
                typeData.SetPropertyConverter(dpOrPiOrMi, converterType);
#endif 
            }
 
            return converterType; 
        }
 
#if !PBTCOMPILER
        // Returns the TypeConverter applied to the given property iself.
        // If not found returns the TypeConverter applied to the given property's type.
        // Throws a XamlParseException if no TypeConverter is found. 
        internal TypeConverter GetPropertyConverter(Type propType, object dpOrPiOrMi)
        { 
            Debug.Assert(null != propType, "Null passed for propType to GetPropertyConverter"); 
            TypeConverter typeConverter = null;
 
            TypeInformationCacheData typeData = GetCachedInformationForType(propType) as TypeInformationCacheData;

            // If the current value being parsed is a property value then we must look
            // if there is special TypeConverter specified as attribute for this property 
            if (null != dpOrPiOrMi)
            { 
                object ret = typeData.PropertyConverters[dpOrPiOrMi]; 
                if (null != ret)
                { 
                    typeConverter = (TypeConverter)ret;
                    return typeConverter;
                }
 
                // Get the memberInfo from the DP, PropertyInfo(CLR) or MethodInfo(Attached) for the property
                MemberInfo memberInfo = TypeConverterHelper.GetMemberInfoForPropertyConverter(dpOrPiOrMi); 
                if (memberInfo != null) 
                {
                    // If not found, next try looking for the TypeConverter on the property itself using reflection. 
                    Type converterType = TypeConverterHelper.GetConverterType(memberInfo);
                    if (converterType != null)
                    {
                        // create an instance of the TypeConverter if found 
                        typeConverter = CreateInstance(converterType) as TypeConverter;
                    } 
                } 
            }
 
            // If no TypeConverter is found on the property itself, try to find it based on the property's type
            if (typeConverter == null)
            {
                typeConverter = GetTypeConverter(propType); 
            }
 
            // Cache the per property TypeConverter 
            if (dpOrPiOrMi != null)
                typeData.SetPropertyConverter(dpOrPiOrMi, typeConverter); 

            return typeConverter;
        }
#endif 

#endregion TypeConverters 
 
#region Resources
 
        /// 
        /// Given a string, return a key to be used in a dictionary relating to this string.
        /// If the string is a simple string, just return that.  If the string represents a
        /// Typeof declaration, then return the Type that maps to that string. 
        /// Note that this can return null if the key is not resolved.  It is up to the caller
        /// to throw the appropriate error message in that case. 
        ///  
        internal object GetDictionaryKey(string keyString, ParserContext context)
        { 
             if (keyString.Length > 0 &&
                 (Char.IsWhiteSpace(keyString[0]) ||
                  Char.IsWhiteSpace(keyString[keyString.Length-1])))
             { 
                keyString = keyString.Trim();
             } 
             return keyString; 
        }
 
#endregion Resources

#if !PBTCOMPILER
 
#region ConstructorInfos
 
        ///  
        /// Fetches the cached ConstructorInfos if there exists one or
        /// then creates a new one and caches it for later. 
        /// 
        internal ConstructorData GetConstructors(Type type)
        {
            // Create a cache if it does not already exist 
            if (_constructorInformationCache == null)
            { 
                _constructorInformationCache = new HybridDictionary(3); 
            }
 
            // Add an entry for the current type if it does not already exist
            if (!_constructorInformationCache.Contains(type))
            {
                _constructorInformationCache[type] = new ConstructorData(type.GetConstructors(BindingFlags.Public | BindingFlags.Instance)); 
            }
 
            // Return the cached value 
            return (ConstructorData)_constructorInformationCache[type];
        } 

        /// 
        /// Helper class that is used to store constructor information for a type
        ///  
        internal class ConstructorData
        { 
            #region Constructors 

            internal ConstructorData(ConstructorInfo[] constructors) 
            {
                _constructors = constructors;
            }
 
            #endregion Constructors
 
            #region Methods 

            ///  
            /// Fetches the cached ParameterInfos if there exists one or
            /// then creates a new one and caches it for later.
            /// 
            internal ParameterInfo[] GetParameters(int constructorIndex) 
            {
                // Create a parameters Cache if it does not already exist 
                if (_parameters == null) 
                {
                    Debug.Assert(_constructors != null, "This operation is legal only after the constructors have been fetched"); 
                    _parameters = new ParameterInfo[_constructors.Length][];
                }

                // Add an entry for the current constructor if it does not already exist 
                if (_parameters[constructorIndex] == null)
                { 
                    _parameters[constructorIndex] = _constructors[constructorIndex].GetParameters(); 
                }
 
                // Return the cached value
                return _parameters[constructorIndex];
            }
 
            #endregion Methods
 
            #region Properties 

            internal ConstructorInfo[] Constructors 
            {
                get { return _constructors; }
            }
 
            #endregion Properties
 
            #region Data 

            private ConstructorInfo[] _constructors; 
            private ParameterInfo[][] _parameters;

            #endregion Data
        } 

#endregion ConstructorInfos 
 
#endif
 
#region TrimSurroundingWhitespace

        /// 
        /// Returns the Cached TrimSurroundingWhitespace for the associated type 
        /// We cache this because the reflection lookup on the attribute
        /// is slow. 
        ///  
        /// type to return the TrimSurroundingWhitespaceAttribute for
        /// The TrimSurroundingWhitespace value for t 
        internal bool GetCachedTrimSurroundingWhitespace(Type t)
        {
            TypeInformationCacheData typeInformation = GetCachedInformationForType(t);
 
            // if first time asked for the layout Type get it.
            if (!typeInformation.TrimSurroundingWhitespaceSet) 
            { 
                typeInformation.TrimSurroundingWhitespace = GetTrimSurroundingWhitespace(t);
                typeInformation.TrimSurroundingWhitespaceSet = true; 
            }

            return typeInformation.TrimSurroundingWhitespace;
        } 

        ///  
        ///  Helper function for  use to find out the TrimSurroundingWhitespace 
        ///  associated with a Type.
        ///  
        private bool GetTrimSurroundingWhitespace(Type type)
        {
            Debug.Assert(null != type, "null value for type passed to GetWhitespace");
 
            // in retail return default.
            if (null != type) 
            { 
#if !PBTCOMPILER
                TrimSurroundingWhitespaceAttribute[] trimAttribute = 
                    type.GetCustomAttributes(typeof(TrimSurroundingWhitespaceAttribute),true )
                    as TrimSurroundingWhitespaceAttribute[];

                if (trimAttribute.Length > 0) 
                {
                    Debug.Assert(1 == trimAttribute.Length,"More than one TrimWhitespace Attribute"); 
                    return true; 
                }
#else 
                // Reflecting for attributes doesn't work on asmmeta files, so
                // we have to hard code known layout types here.  This is very
                // fragile, but we'll fix it in M8.2. - It's end of M11 already though...
                if (KnownTypes.Types[(int)KnownElements.LineBreak].IsAssignableFrom(type)) 
                {
                    // 
                    return true; 
                }
#endif 
            }
            return false;
        }
 
#endregion TrimSurroundingWhitespace
 
#region Exceptions 

        // 
        // ThrowException wrappers for 0-3 parameter SRIDs
        //

        private void ThrowException(string id) 
        {
            ThrowExceptionWithLine(SR.Get(id), null); 
        } 

        internal void ThrowException(string id, string parameter) 
        {
            ThrowExceptionWithLine(SR.Get(id, parameter), null);
        }
 
        private void ThrowException(string id, string parameter1, string parameter2)
        { 
            ThrowExceptionWithLine(SR.Get(id, parameter1, parameter2), null); 
        }
 
        private void ThrowException(string id, string parameter1, string parameter2, string parameter3)
        {
            ThrowExceptionWithLine(SR.Get(id, parameter1, parameter2, parameter3), null);
        } 

 
 
        //
        // ThrowException wrapper that just adds the line number & position. 
        //

        internal void ThrowExceptionWithLine(string message, Exception innerException)
        { 
            XamlParseException.ThrowException(message, innerException, _lineNumber, _linePosition);
        } 
 

#endregion Exceptions 

#region Properties

        ///  
        /// Hashtable where key is the xmlNamespace, and value is the
        /// ClrNamespaceAssemblyPair structure containing clrNamespace and assembly 
        ///  
        internal HybridDictionary PITable
        { 
            get { return _piTable; }
        }

 
        /// 
        /// This is the associated BamlMapTable that contains information about what is 
        /// in a baml stream.  The XamlTypeMapper uses the map table (if present) as a cache 
        /// to store some assembly, type and property information.  If it is not present
        /// then this information is not cached and must be retrieved for every request. 
        /// 
        internal BamlMapTable MapTable
        {
            get { return _mapTable; } 
            set { _mapTable = value; }
        } 
 
        /// 
        /// Line number used for error reporting 
        /// 
        internal int LineNumber
        {
            set { _lineNumber = value; } 
        }
 
        ///  
        /// Line position used for error reporting
        ///  
        internal int LinePosition
        {
            set { _linePosition = value; }
        } 

#if !PBTCOMPILER 
        ///  
        ///  Return the hashtable that is keyed by xml namespace uri and
        ///  has values that are collection of NamespaceMapEntry objects for that 
        ///  xml namespace.
        /// 
        internal Hashtable NamespaceMapHashList
        { 
            get { return _namespaceMapHashList; }
        } 
 
        internal System.Xaml.XamlSchemaContext SchemaContext
        { 
            get
            {
                if (_schemaContext == null)
                { 
                    _schemaContext = new XamlTypeMapperSchemaContext(this);
                } 
                return _schemaContext; 
            }
        } 
#else
        // true if the Type Mapper can allow protected attributes.
        // This will be the case for a markup sub-classed root element only.
        internal bool IsProtectedAttributeAllowed 
        {
            get { return _isProtectedAttributeAllowed; } 
            set { _isProtectedAttributeAllowed = value; } 
        }
 
        internal void ResetMapper()
        {
            _piTable.Clear();
            _piReverseTable.Clear(); 
            _lineNumber = 0;
            _linePosition = 0; 
            _isProtectedAttributeAllowed = false; 

            NamespaceMapEntry[] defaultNsMaps = _namespaceMapHashList[XamlReaderHelper.DefaultNamespaceURI] as NamespaceMapEntry[]; 
            NamespaceMapEntry[] definitionNsMaps = _namespaceMapHashList[XamlReaderHelper.DefinitionNamespaceURI] as NamespaceMapEntry[];
            NamespaceMapEntry[] definitionMetroNsMaps = _namespaceMapHashList[XamlReaderHelper.DefinitionMetroNamespaceURI] as NamespaceMapEntry[];

            _namespaceMapHashList.Clear(); 
            if (null != defaultNsMaps)
            { 
                _namespaceMapHashList.Add(XamlReaderHelper.DefaultNamespaceURI, defaultNsMaps); 
            }
            if (null != definitionNsMaps) 
            {
                _namespaceMapHashList.Add(XamlReaderHelper.DefinitionNamespaceURI, definitionNsMaps);
            }
            if (null != definitionMetroNsMaps) 
            {
                _namespaceMapHashList.Add(XamlReaderHelper.DefinitionMetroNamespaceURI, definitionMetroNsMaps); 
            } 
        }
#endif 
#endregion Properties

        #region Data
 
        // Class used for Type information data cache.
        internal class TypeInformationCacheData 
        { 
            /// 
            /// Create a new instance of the type cache.  Note that the type of this cached 
            /// data is not stored anywhere in this object.  The type that this object pertains
            /// to is stored as the key in the _typeInformationCache dictionary.
            /// 
            internal TypeInformationCacheData(Type baseType) 
            {
                _baseType = baseType; 
            } 

            ///  
            /// Urt Namespace for this type
            /// 
            internal string ClrNamespace
            { 
#if !PBTCOMPILER
                get { return _clrNamespace; } 
#endif 
                set { _clrNamespace = value; }
            } 

#if !PBTCOMPILER
            /// 
            /// The parent type in the inheritance hierarchy of this type.  This is 
            /// stored here since BaseType lookups take some time.
            ///  
            internal Type BaseType 
            {
                get { return _baseType; } 
            }

            /// 
            /// TypeConverter associted with this type, if there is one.  This is stored 
            /// here so that GetTypeConverter does not need to be called as often.
            ///  
            internal TypeConverter Converter 
            {
                get { return _typeConverter; } 
                set { _typeConverter = value; }
            }
#endif
            // The type of the TypeConverter 
            internal Type TypeConverterType
            { 
                get { return _typeConverterType; } 
                set { _typeConverterType = value; }
            } 

            /// 
            /// TrimSurroundingWhitespace value for this type.
            ///  
            internal bool TrimSurroundingWhitespace
            { 
                get { return _trimSurroundingWhitespace; } 
                set { _trimSurroundingWhitespace = value; }
            } 

            /// 
            /// Flag to indicate if we have cached the TrimSurroundingWhitespace
            ///  
            internal bool TrimSurroundingWhitespaceSet
            { 
                get { return _trimSurroundingWhitespaceSet; } 
                set { _trimSurroundingWhitespaceSet = value; }
            } 

            /// 
            /// Get the DependencyProperty from the Hashtable of PropertyAndType
            /// keyed by DependencyProperty name 
            /// 
            internal PropertyAndType GetPropertyAndType(string dpName) 
            { 
                if (_dpLookupHashtable == null)
                { 
                    _dpLookupHashtable = new Hashtable();
                    return null;
                }
 
                return _dpLookupHashtable[dpName] as PropertyAndType;
            } 
 

            ///  
            /// Set a new PropertyAndType in the DependencyProperty information Hashtable.
            /// 
            internal void SetPropertyAndType(
                string          dpName, 
                PropertyInfo    dpInfo,
                Type            ownerType, 
                bool            isInternal) 
            {
                Debug.Assert(_dpLookupHashtable != null, 
                    "GetPropertyAndType must always be called before SetPropertyAndType");

                // add the type taking a lock
                PropertyAndType pAndT = _dpLookupHashtable[dpName] as PropertyAndType; 
                if (pAndT == null)
                { 
                    _dpLookupHashtable[dpName] = new PropertyAndType(null, dpInfo, false, true, ownerType, isInternal); 
                }
                else 
                {
                    pAndT.PropInfo = dpInfo;
                    pAndT.PropInfoSet = true;
                    pAndT.IsInternal = isInternal; 
                }
            } 
 
            /// 
            /// TypeConverters based upon attributes on property 
            /// 
            internal HybridDictionary PropertyConverters
            {
                get 
                {
                    if (null == _propertyConverters) 
                    { 
                        _propertyConverters = new HybridDictionary();
                    } 

                    return _propertyConverters;
                }
            } 

            ///  
            /// Set a new PropertyConverter for the given property. 
            /// NOTE: This method takes a lock on the table. So to set
            /// values into the table you must use this method. 
            /// 
            internal void SetPropertyConverter(
                object dpOrPi,
#if !PBTCOMPILER 
                TypeConverter converter)
#else 
                Type converter) 
#endif
            { 
                _propertyConverters[dpOrPi] = converter;
            }

            // Private data members 
            string        _clrNamespace;
            Type          _baseType; 
            bool          _trimSurroundingWhitespace; 
            Hashtable     _dpLookupHashtable;  // Hashtable of PropertyAndType keyed by dp name
            HybridDictionary     _propertyConverters = new HybridDictionary(); // Dictionary of TypeConverters keyed on dpOrPi 
            bool          _trimSurroundingWhitespaceSet;
#if !PBTCOMPILER
            TypeConverter _typeConverter;
#endif 
            Type          _typeConverterType;
        } 
 
        // DP setter method, PropertyInfo and Type record held in _dpLookupHashtable
        internal class PropertyAndType 
        {
            public PropertyAndType (MethodInfo dpSetter,
                                    PropertyInfo dpInfo,
                                    bool setterSet, 
                                    bool propInfoSet,
                                    Type ot, 
                                    bool isInternal) 
            {
                Setter      = dpSetter; 
                PropInfo    = dpInfo;
                OwnerType   = ot;
                SetterSet   = setterSet;
                PropInfoSet = propInfoSet; 
                IsInternal  = isInternal;
            } 
 
            public PropertyInfo PropInfo;
            public MethodInfo   Setter; 
            public Type         OwnerType;
            public bool         PropInfoSet;
            public bool         SetterSet;
            public bool         IsInternal; 
        }
 
        // Constants that identify special types of string values 
        internal const string MarkupExtensionTypeString = "Type ";
        internal const string MarkupExtensionStaticString = "Static "; 
//        internal const string MarkupExtensionNullString = "Null";
        internal const string MarkupExtensionDynamicResourceString = "DynamicResource ";

        // If the case or name of the assembly name changes in the Framework build, 
        // then the following will have to change also.
        internal const string PresentationFrameworkDllName  = "PresentationFramework"; 
 
        // Namespace & classname of the generated helper class for accessing allowed internal types in PT.
        internal const string GeneratedNamespace = "XamlGeneratedNamespace"; 
        internal const string GeneratedInternalTypeHelperClassName = "GeneratedInternalTypeHelper";

#if !PBTCOMPILER
        internal const string MarkupExtensionTemplateBindingString = "TemplateBinding "; 
#else
        private static bool _hasInternals = false; 
        private static bool _hasLocalReference = false; 
        private bool _isProtectedAttributeAllowed = false;
        internal static Assembly AssemblyWB = null; 
        internal static Assembly AssemblyPC = null;
        internal static Assembly AssemblyPF = null;
#endif
        // Map table associated with this XamlTypeMapper.  This contains information 
        // about what is stored in BAML.  The XamlTypeMapper makes use of the caches in
        // the BamlMapTable to store some assembly, type and property information. 
        BamlMapTable _mapTable; 

        // Array of assembly names that can be used when resolving clr namespaces 
        string[] _assemblyNames;

        // array or namespace map entries such as `http:// mappings.
        NamespaceMapEntry[] _namespaceMaps; 

        // HashTable of cached type lookups and the serializers for that type.  These 
        // are always TypeAndSerializer objects 
        Hashtable _typeLookupFromXmlHashtable = new Hashtable();
 
        // Hash table of mappings between xmlNamespace and mappings
        Hashtable _namespaceMapHashList = new Hashtable();

        // Hashtable where the key is the fullTypeName + '#' + propertyName and the value 
        HybridDictionary _typeInformationCache = new HybridDictionary();
 
#if !PBTCOMPILER 
        // Hashtable where the key is the type and the value is the set of constructors for that type
        HybridDictionary _constructorInformationCache; 

        // A SchemaContext that respects the namespace mappings, PIs, and assembly paths
        // passed in to this TypeMapper
        private XamlTypeMapperSchemaContext _schemaContext; 
#endif
 
        // Hashtable where key is the xmlNamespace, and value is the 
        // ClrNamespaceAssemblyPair structure containing clrNamespace and assembly
        HybridDictionary _piTable =  new HybridDictionary(); 

        // Hashtable where key is the clrNamespace + "#" + assemblyName and the
        // value is the corresponding xmlNamespace.  This is used for fast lookups
        // of xmlnamespace if you know the assembly and clr namespace. 
        Dictionary _piReverseTable = new Dictionary();
 
        // Hashtable where key is the assembly's short name that has been uppercased, 
        // and the value is a path where that assembly can be loaded from.
        // Always lock on this object when writing to it 
        HybridDictionary _assemblyPathTable = new HybridDictionary();

        // true if referenced assemblies in the _assemblyPathTable have been loaded
        bool _referenceAssembliesLoaded = false; 

        // Line number and position in original Xaml file corresponding to the 
        // current BAML record. 
        int _lineNumber = 0;
        int _linePosition = 0; 

        // Cache of namespace and assemblies.
        private static XmlnsCache _xmlnsCache = null;
 
#endregion Data
 
#endregion Internal 
    }
 
    // Todo: Move to a separate file.

    // Type of object and type of Serializer for that type.  If this type
    // also contains an [XmlLang] property, this caches the property info also. 
    // These are contained in the _typeLookupFromXmlHashtable hastable
    internal class TypeAndSerializer 
    { 
        public TypeAndSerializer()
        { 
        }

        public Type ObjectType = null;
        public Type SerializerType = null; 
        public bool IsSerializerTypeSet = false;
        public PropertyInfo XmlLangProperty; 
    } 

    ///  
    /// Contains information the XamlTypeMapper uses for Mapping between an xml
    /// XmlNamespace and what Assembly, Namespace to look in.
    /// 
    [DebuggerDisplay("'{_xmlNamespace}'={_clrNamespace}:{_assemblyName}")] 
#if PBTCOMPILER
    internal class NamespaceMapEntry 
#else 
    public class NamespaceMapEntry
#endif 
    {

        #region Constructors
 
        ///
        /// NamespaceMapEntry default constructor 
        /// 
        public NamespaceMapEntry()
        { 
        }

        /// 
        /// Constructor 
        /// 
        /// The XML NamespaceURi 
        /// Assembly to use when resolving a Tag 
        /// Namespace within the assembly
        public NamespaceMapEntry(string xmlNamespace,string assemblyName,string clrNamespace) 
        {
            if (xmlNamespace == null)
                throw new ArgumentNullException("xmlNamespace");
 
            if (assemblyName == null)
                throw new ArgumentNullException("assemblyName"); 
 
            if (clrNamespace == null)
                throw new ArgumentNullException("clrNamespace"); 

            _xmlNamespace = xmlNamespace;
            _assemblyName = assemblyName;
            _clrNamespace = clrNamespace; 
        }
 
        ///  
        /// Constructor
        ///  
        /// The XML NamespaceURi
        /// Assembly to use when resolving a Tag
        /// Namespace within the assembly
        /// Path to use when loading assembly.  This may be null. 
         internal NamespaceMapEntry(
                string xmlNamespace, 
                string assemblyName, 
                string clrNamespace,
                string assemblyPath) : this(xmlNamespace, assemblyName, clrNamespace) 
        {
            _assemblyPath = assemblyPath;
        }
 
        #endregion Constructors
 
 
        #region Properties
 
        /// 
        /// Xml namespace specified in the constructor
        /// 
        public string XmlNamespace 
        {
            get { return _xmlNamespace; } 
            set 
            {
                if (value == null) 
                {
                    throw new ArgumentNullException("value");
                }
                if (_xmlNamespace == null) 
                {
                    _xmlNamespace = value; 
                } 
            }
        } 

        /// 
        /// AssemblyName specified in the constructor
        ///  
        public string AssemblyName
        { 
            get { return _assemblyName; } 
            set
            { 
                if (value == null)
                {
                    throw new ArgumentNullException("value");
                } 
                if (_assemblyName == null)
                { 
                    _assemblyName = value; 
                }
            } 
        }

        /// 
        /// ClrNamespace specified within the constructor 
        /// 
        public string ClrNamespace 
        { 
            get { return _clrNamespace; }
            set 
            {
                if (value == null)
                {
                    throw new ArgumentNullException("value"); 
                }
                if (_clrNamespace == null) 
                { 
                    _clrNamespace = value;
                } 
            }
        }

 
        #endregion Properties
 
        ///  
        /// returns instance of the assembly associate with this
        /// namespace map 
        /// 
        internal Assembly Assembly
        {
            get 
            {
                if (null == _assembly && _assemblyName.Length > 0) 
                { 
#if PBTCOMPILER
                    // NOTE: At compile time a local assembly can already be loaded if being 
                    // referenced by dehydrated assemblies and so we should attempt to return
                    // that.
                    if (_isLocalAssembly)
                    { 
                        string assemblyNameLookup = _assemblyName.ToUpper(CultureInfo.InvariantCulture);
 
                        // Check if the assembly has already been loaded. 
                        if (!ReflectionHelper.HasAlreadyReflectionOnlyLoaded(assemblyNameLookup))
                        { 
                            return null;
                        }
                    }
 
#endif
                    _assembly = ReflectionHelper.LoadAssembly(_assemblyName, _assemblyPath); 
                } 

                return _assembly; 
            }
        }

        ///  
        /// Get and set the path to use when loading the assembly.
        ///  
        internal string AssemblyPath 
        {
            get { return _assemblyPath; } 
            set { _assemblyPath = value; }
        }

#if PBTCOMPILER 
        internal bool LocalAssembly
        { 
            get { return _isLocalAssembly; } 
            set { _isLocalAssembly = value; }
        } 

        bool     _isLocalAssembly;
#endif
 
#region Data
 
        string   _xmlNamespace; 
        string   _assemblyName;
        string   _assemblyPath; 
        Assembly _assembly;
        string   _clrNamespace;

#endregion Data 

    } 
 
    // This is a convenience holder for all the possible IDs that Xaml understands which could
    // be on an object element. 
    internal class XamlObjectIds
    {
        public string Name = null;
        public string Uid = null; 
        public object Key = null;
    } 
 

#region XmlParserDefaults Class 

    // class for getting and setting mapping defaults.
    internal static class XmlParserDefaults
    { 

#region Methods 
 
        /// 
        ///  Instance of XamlTypeMapper to use if none is specified in the 
        ///  ParserContext. XamlTypeMapper returned is has its assembly and namespace
        ///  maps initialized to those set
        ///  via SetDefaultXmlMapping() or one built from our internal defaults.
        ///  
        internal static XamlTypeMapper DefaultMapper
        { 
            get 
            {
                return new XamlTypeMapper(GetDefaultAssemblyNames(),GetDefaultNamespaceMaps()); 
            }
        }

#endregion Methods 

#region Properties 
 
        /// 
        /// Returns an array of the DefaultAssemblyNames 
        /// 
        internal static string[] GetDefaultAssemblyNames()
        {
            return (string[])_defaultAssemblies.Clone(); 
        }
 
        ///  
        /// Returns array of the DefaultNamespaceMaps
        ///  
        internal static NamespaceMapEntry[] GetDefaultNamespaceMaps()
        {
            return (NamespaceMapEntry[])_defaultNamespaceMapTable.Clone();
        } 

#endregion Properties 
 
#region Data
 
        // array of our defaultAssemblies.
        private static readonly string[] _defaultAssemblies = {"WindowsBase", "PresentationCore", "PresentationFramework"};

        // array of namespaceMaps the map an xmlns namespaceURI 
        // to the assembly and urtNamespace to search in when resolving the xml
 
        private static readonly NamespaceMapEntry[] _defaultNamespaceMapTable = { }; 

#endregion Data 
    }
#endregion XmlParserDefaults Class

} 

 
 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK