| File: System\Xaml\Context\XamlParserContext.cs | Web Access |
| Project: src\wpf\src\Microsoft.DotNet.Wpf\src\System.Xaml\System.Xaml.csproj (System.Xaml) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. #nullable disable using System.Reflection; using System.Xaml; using MS.Internal.Xaml.Parser; namespace MS.Internal.Xaml.Context { internal class XamlParserContext : XamlContext { private XamlContextStack<XamlParserFrame> _stack; private Dictionary<string, string> _prescopeNamespaces; public bool AllowProtectedMembersOnRoot { get; set; } public Func<string, string> XmlNamespaceResolver { get; set; } public XamlParserContext(XamlSchemaContext schemaContext, Assembly localAssembly) :base(schemaContext) { _stack = new XamlContextStack<XamlParserFrame>(()=>new XamlParserFrame()); _prescopeNamespaces = new Dictionary<string, string>(); base._localAssembly = localAssembly; } // ----- abstracts overriden from XamlContext. public override void AddNamespacePrefix(string prefix, string xamlNS) { _prescopeNamespaces.Add(prefix, xamlNS); } public string FindNamespaceByPrefixInParseStack(string prefix) { string xamlNs; if (_prescopeNamespaces is not null) { if (_prescopeNamespaces.TryGetValue(prefix, out xamlNs)) { return xamlNs; } } XamlParserFrame frame = _stack.CurrentFrame; while (frame.Depth > 0) { if (frame.TryGetNamespaceByPrefix(prefix, out xamlNs)) { return xamlNs; } frame = (XamlParserFrame)frame.Previous; } return null; } public override string FindNamespaceByPrefix(string prefix) { // For proper operation of some corner senarios the XmlNamespaceResolver // must be set. But if it isn't we fall back to a look in our own stack. // Senarios that REQUIRE an XmlNamespaceResolver // 1) Prefix defs that ONLY exist in the XmlNsManager are only found this way // 2) Prefix defs on MarkupCompat Tags have effect but don't appear // in the Xml node stream the XAML parser sees. // But for normal XAML the XmlNamespaceResolver does not need to be used. if (XmlNamespaceResolver is not null) { return XmlNamespaceResolver(prefix); } return FindNamespaceByPrefixInParseStack(prefix); } public override IEnumerable<NamespaceDeclaration> GetNamespacePrefixes() { XamlParserFrame frame = _stack.CurrentFrame; HashSet<string> keys = new HashSet<string>(); while (frame.Depth > 0) { if (frame._namespaces is not null) { foreach (NamespaceDeclaration namespaceDeclaration in frame.GetNamespacePrefixes()) { if (keys.Add(namespaceDeclaration.Prefix)) { yield return namespaceDeclaration; } } } frame = (XamlParserFrame)frame.Previous; } if (_prescopeNamespaces is not null) { foreach (KeyValuePair<string, string> kvp in _prescopeNamespaces) { if (keys.Add(kvp.Key)) { yield return new NamespaceDeclaration(kvp.Value, kvp.Key); } } } } // Only pass rootObjectType if the member is being looked up on the root object internal override bool IsVisible(XamlMember member, XamlType rootObjectType) { if (member is null) { return false; } Type allowProtectedForType = null; if (AllowProtectedMembersOnRoot && rootObjectType is not null) { allowProtectedForType = rootObjectType.UnderlyingType; } // First check if the property setter is visible if (member.IsWriteVisibleTo(LocalAssembly, allowProtectedForType)) { return true; } // If the property setter is not visible, but the property getter is, treat the property // as if it were read-only if (member.IsReadOnly || (member.Type is not null && member.Type.IsUsableAsReadOnly)) { return member.IsReadVisibleTo(LocalAssembly, allowProtectedForType); } return false; } // ----- new public methods. public void PushScope() { _stack.PushScope(); if (_prescopeNamespaces.Count > 0) { _stack.CurrentFrame.SetNamespaces(_prescopeNamespaces); _prescopeNamespaces = new Dictionary<string, string>(); } } public void PopScope() { _stack.PopScope(); } internal void InitBracketCharacterCacheForType(XamlType extensionType) { CurrentEscapeCharacterMapForMarkupExtension = SchemaContext.InitBracketCharacterCacheForType(extensionType); } /// <summary> /// Finds the list of parameters of the constructor with the most number /// of arguments. /// </summary> internal void InitLongestConstructor(XamlType xamlType) { IEnumerable<ConstructorInfo> constructors = xamlType.GetConstructors(); ParameterInfo[] constructorParameters = null; int parameterCount = 0; foreach (ConstructorInfo ctr in constructors) { ParameterInfo[] parInfo = ctr.GetParameters(); if (parInfo.Length >= parameterCount) { parameterCount = parInfo.Length; constructorParameters = parInfo; } } CurrentLongestConstructorOfMarkupExtension = constructorParameters; } // FxCop says this is never called // public int Depth // { // get { return _stack.Depth; } // } public XamlType CurrentType { get { return _stack.CurrentFrame.XamlType; } set { _stack.CurrentFrame.XamlType = value; } } internal BracketModeParseParameters CurrentBracketModeParseParameters { get { return _stack.CurrentFrame.BracketModeParseParameters; } set { _stack.CurrentFrame.BracketModeParseParameters = value; } } internal ParameterInfo[] CurrentLongestConstructorOfMarkupExtension { get { return _stack.CurrentFrame.LongestConstructorOfCurrentMarkupExtensionType; } set { _stack.CurrentFrame.LongestConstructorOfCurrentMarkupExtensionType = value; } } internal Dictionary<string, SpecialBracketCharacters> CurrentEscapeCharacterMapForMarkupExtension { get { return _stack.CurrentFrame.EscapeCharacterMapForMarkupExtension; } set { _stack.CurrentFrame.EscapeCharacterMapForMarkupExtension = value; } } // This property refers to a namespace specified explicitly in the XAML document. // If this is an implicit type (e.g. GO, x:Data, implicit array) just leave it as null. public string CurrentTypeNamespace { get { return _stack.CurrentFrame.TypeNamespace; } set { _stack.CurrentFrame.TypeNamespace = value; } } public bool CurrentInContainerDirective { get { return _stack.CurrentFrame.InContainerDirective; } set { _stack.CurrentFrame.InContainerDirective = value; } } // FxCop says this is not called // public XamlType ParentType // { // get { return _stack.PreviousFrame.XamlType; } // } public XamlMember CurrentMember { get { return _stack.CurrentFrame.Member; } set { _stack.CurrentFrame.Member = value; } } // FxCop says this is not called // public XamlProperty MemberProperty // { // get { return _stack.PreviousFrame.Member; } // } public int CurrentArgCount { get { return _stack.CurrentFrame.CtorArgCount; } set { _stack.CurrentFrame.CtorArgCount = value; } } public bool CurrentForcedToUseConstructor { get { return _stack.CurrentFrame.ForcedToUseConstructor; } set { _stack.CurrentFrame.ForcedToUseConstructor = value; } } public bool CurrentInItemsProperty { get { return _stack.CurrentFrame.Member == XamlLanguage.Items; } } public bool CurrentInInitProperty { get { return _stack.CurrentFrame.Member == XamlLanguage.Initialization; } } public bool CurrentInUnknownContent { get { return _stack.CurrentFrame.Member == XamlLanguage.UnknownContent; } } public bool CurrentInImplicitArray { get { return _stack.CurrentFrame.InImplicitArray; } set { _stack.CurrentFrame.InImplicitArray = value; } } public bool CurrentInCollectionFromMember { get { return _stack.CurrentFrame.InCollectionFromMember; } set { _stack.CurrentFrame.InCollectionFromMember = value; } } public XamlType CurrentPreviousChildType { get { return _stack.CurrentFrame.PreviousChildType; } set { _stack.CurrentFrame.PreviousChildType = value; } } public bool CurrentMemberIsWriteVisible() { Type allowProtectedForType = null; if (AllowProtectedMembersOnRoot && _stack.Depth == 1) { allowProtectedForType = CurrentType.UnderlyingType; } return CurrentMember.IsWriteVisibleTo(LocalAssembly, allowProtectedForType); } public bool CurrentTypeIsRoot { get { return _stack.CurrentFrame.XamlType is not null && _stack.Depth == 1; } } } }