XamlValidatingReader.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / XamlBuildTask / Microsoft / Build / Tasks / Xaml / XamlValidatingReader.cs / 1305376 / XamlValidatingReader.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------

namespace Microsoft.Build.Tasks.Xaml 
{
    using System; 
    using System.Collections.Generic; 
    using System.ComponentModel;
    using System.Diagnostics; 
    using System.Linq;
    using System.Text;
    using System.Xaml;
    using System.Xaml.Schema; 
    using System.Reflection;
    using System.Runtime; 
    using System.Globalization; 
    using System.Diagnostics.CodeAnalysis;
    using System.IO; 

    internal class XamlValidatingReader : XamlWrappingReader
    {
        XamlStackWriter _stack = new XamlStackWriter(); 
        Assembly assembly;
        Type definedType; 
        string rootNamespace; 
        string localAssemblyName;
        string realAssemblyName; 

        public event EventHandler OnValidationError;

        public XamlValidatingReader(XamlReader underlyingReader, Assembly assembly, string rootNamespace, string realAssemblyName) 
            : base(underlyingReader)
        { 
            this.assembly = assembly; 
            this.definedType = null;
            this.rootNamespace = rootNamespace; 
            this.localAssemblyName = assembly != null ? assembly.GetName().Name : null;
            this.realAssemblyName = realAssemblyName;
        }
 
        [SuppressMessage(FxCop.Category.Design, FxCop.Rule.DoNotCatchGeneralExceptionTypes,
            Justification = "Need to catch and log the exception here so that all the errors, including the exception thrown, are surfaced.")] 
        public override bool Read() 
        {
            if (!base.Read()) 
            {
                return false;
            }
 
            try
            { 
                if (_stack.Depth == 0) 
                {
                    State_AtRoot(); 
                }
                else if (_stack.TopFrame.FrameType == XamlStackFrameType.Member)
                {
                    if (_stack.TopFrame.IsSet() && !AllowsMultiple(_stack.TopFrame.Member)) 
                    {
                        State_ExpectEndMember(); 
                    } 
                    else
                    { 
                        State_InsideMember();
                    }
                }
                else 
                {
                    if (_stack.TopFrame.FrameType != XamlStackFrameType.Object && _stack.TopFrame.FrameType != XamlStackFrameType.GetObject) 
                    { 
                        ValidationError(SR.UnexpectedXaml);
                    } 
                    State_InsideObject();
                }
            }
            catch (FileLoadException e) 
            {
                if (Fx.IsFatal(e)) 
                { 
                    throw;
                } 
                ValidationError(SR.AssemblyCannotBeResolved(XamlBuildTaskServices.FileNotLoaded));
            }
            catch (Exception e)
            { 
                if (Fx.IsFatal(e))
                { 
                    throw; 
                }
                ValidationError(e.Message); 
            }
            return true;
        }
 
        protected virtual void ValidationError(string message, params object[] args)
        { 
            EventHandler handler = OnValidationError; 
            if (handler != null)
            { 
                string formattedMessage =
                    (args == null || args.Length == 0) ?
                    message : string.Format(CultureInfo.InvariantCulture, message, args);
                handler(this, new ValidationEventArgs(formattedMessage, LineNumber, LinePosition)); 
            }
        } 
 
        private void State_AtRoot()
        { 
            switch (NodeType)
            {
                case XamlNodeType.NamespaceDeclaration:
                    return; 
                case XamlNodeType.StartObject:
                    ValidateUnknown(Type); 
                    break; 
                default:
                    ValidationError(SR.UnexpectedXaml); 
                    break;
            }
            _stack.WriteNode(this);
        } 

        private void State_InsideObject() 
        { 
            switch (NodeType)
            { 
                case XamlNodeType.NamespaceDeclaration:
                    return;
                case XamlNodeType.StartMember:
                    if (_stack.TopFrame.IsSet(Member)) 
                    {
                        ValidationError(SR.UnexpectedXaml); 
                    } 
                    if (_stack.TopFrame.FrameType == XamlStackFrameType.GetObject)
                    { 
                        ValidateMemberOnGetObject(Member);
                    }
                    else
                    { 
                        ValidateUnknown(Member);
                        ValidateMemberOnType(Member, _stack.TopFrame.Type); 
                    } 
                    break;
                case XamlNodeType.EndObject: 
                    break;
                default:
                    ValidationError(SR.UnexpectedXamlDupMember);
                    break; 
            }
            _stack.WriteNode(this); 
        } 

        private void State_InsideMember() 
        {
            switch (NodeType)
            {
                case XamlNodeType.NamespaceDeclaration: 

                    return; 
                case XamlNodeType.StartObject: 
                    ValidateUnknown(Type);
                    ValidateTypeToMemberOnStack(Type); 
                    break;
                case XamlNodeType.GetObject:
                    ValidateGetObjectOnMember(_stack.TopFrame.Member);
                    break; 
                case XamlNodeType.Value:
                    ValidateValueToMemberOnStack(Value); 
                    break; 
                case XamlNodeType.EndMember:
                    break; 
                default:
                    ValidationError(SR.UnexpectedXaml);
                    break;
            } 
            _stack.WriteNode(this);
        } 
 
        private void State_ExpectEndMember()
        { 
            if (NodeType != XamlNodeType.EndMember)
            {
                ValidationError(SR.UnexpectedXaml);
            } 
            _stack.WriteNode(this);
        } 
 
        private void ValidateGetObjectOnMember(XamlMember member)
        { 
            if (member == XamlLanguage.Items || member == XamlLanguage.PositionalParameters)
            {
                ValidationError(SR.UnexpectedXaml);
            } 
            else if (!member.IsUnknown && member != XamlLanguage.UnknownContent &&
                !member.Type.IsCollection && !member.Type.IsDictionary) 
            { 
                ValidationError(SR.UnexpectedXaml);
            } 
        }

        private void ValidateMemberOnGetObject(XamlMember member)
        { 
            if (member != XamlLanguage.Items)
            { 
                ValidationError(SR.UnexpectedXaml); 
            }
        } 

        private void ValidateMemberOnType(XamlMember member, XamlType type)
        {
            if (member.IsUnknown || type.IsUnknown) 
            {
                return; 
            } 
            if (member.IsDirective)
            { 
                if (member == XamlLanguage.Items)
                {
                    if (!type.IsCollection && !type.IsDictionary)
                    { 
                        ValidationError(SR.UnexpectedXamlDictionary(member.Name, GetXamlTypeName(_stack.TopFrame.Type)));
                    } 
                } 
                if (member == XamlLanguage.Class && _stack.Depth > 1)
                { 
                    ValidationError(SR.UnexpectedXamlClass);
                }
            }
            else if (member.IsAttachable) 
            {
                if (!type.CanAssignTo(member.TargetType)) 
                { 
                    ValidationError(SR.UnexpectedXamlAttachableMember(member.Name, GetXamlTypeName(member.TargetType)));
                } 
            }
            else if (!member.IsDirective && !type.CanAssignTo(member.DeclaringType))
            {
                ValidationError(SR.UnexpectedXamlMemberNotAssignable(member.Name, GetXamlTypeName(type))); 
            }
        } 
 
        private void ValidateTypeToMemberOnStack(XamlType type)
        { 
            if (type.IsUnknown)
            {
                return;
            } 
            if (type == XamlLanguage.Null)
            { 
                ValidateValueToMemberOnStack(null); 
            }
            XamlMember member = _stack.TopFrame.Member; 
            if (member == XamlLanguage.PositionalParameters || type.IsMarkupExtension || member.IsUnknown)
            {
                return;
            } 
            if (member == XamlLanguage.Items)
            { 
                XamlType collectionType = GetCollectionTypeOnStack(); 
                if (collectionType == null || collectionType.IsUnknown || collectionType.AllowedContentTypes == null)
                { 
                    return;
                }
                if (!collectionType.AllowedContentTypes.Any(contentType => type.CanAssignTo(contentType)))
                { 
                    ValidationError(SR.UnassignableCollection(GetXamlTypeName(type), GetXamlTypeName(collectionType.ItemType), GetXamlTypeName(collectionType)));
                } 
            } 
            else if (member.IsDirective && (member.Type.IsCollection || member.Type.IsDictionary))
            { 
                XamlType collectionType = member.Type;
                if (collectionType == null || collectionType.IsUnknown || collectionType.AllowedContentTypes == null)
                {
                    return; 
                }
                if (!collectionType.AllowedContentTypes.Any(contentType => type.CanAssignTo(contentType))) 
                { 
                    ValidationError(SR.UnassignableCollection(GetXamlTypeName(type), GetXamlTypeName(collectionType.ItemType), GetXamlTypeName(collectionType)));
                } 
            }
            else if (!type.CanAssignTo(member.Type))
            {
                if (member.DeferringLoader != null) 
                {
                    return; 
                } 
                if (NodeType == XamlNodeType.Value)
                { 
                    ValidationError(SR.UnassignableTypes(GetXamlTypeName(type), GetXamlTypeName(member.Type), member.Name));
                }
                else
                { 
                    ValidationError(SR.UnassignableTypesObject(GetXamlTypeName(type), GetXamlTypeName(member.Type), member.Name));
                } 
            } 
        }
 
        private void ValidateValueToMemberOnStack(object value)
        {
            XamlMember member = _stack.TopFrame.Member;
            if (member.IsUnknown) 
            {
                return; 
            } 
            if (value != null)
            { 
                if (member.IsEvent)
                {
                    if (this.definedType != null && this.definedType.GetMethod(value as string,
                        BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public) == null) 
                    {
                        ValidationError(SR.UnexpectedXamlEventHandlerNotFound(value, definedType.FullName)); 
                    } 
                    return;
                } 
                else if (member == XamlLanguage.Class)
                {
                    string className = value as string;
                    Fx.Assert(!string.IsNullOrEmpty(className), "ClassName cannot be null"); 
                    if (!string.IsNullOrEmpty(this.rootNamespace))
                    { 
                        className = this.rootNamespace + "." + className; 
                    }
                    if (this.assembly != null) 
                    {
                        this.definedType = this.assembly.GetType(className);
                    }
                    return; 
                }
                else if (member.TypeConverter != null) 
                { 
                    return;
                } 
                XamlType typeOfValue = SchemaContext.GetXamlType(value.GetType());
                ValidateTypeToMemberOnStack(typeOfValue);
            }
            else 
            {
                if (member == XamlLanguage.PositionalParameters) 
                { 
                    return;
                } 
                if (member == XamlLanguage.Items)
                {
                    XamlType collectionType = GetCollectionTypeOnStack();
                    if (collectionType == null || collectionType.IsUnknown || collectionType.AllowedContentTypes == null) 
                    {
                        return; 
                    } 
                    if (!collectionType.AllowedContentTypes.Any(contentType => contentType.IsNullable))
                    { 
                        ValidationError(SR.UnassignableCollection("(null)", GetXamlTypeName(collectionType.ItemType), GetXamlTypeName(collectionType)));
                    }
                }
                else 
                {
                    if (!member.Type.IsNullable) 
                    { 
                        ValidationError(SR.UnassignableTypes("(null)", GetXamlTypeName(member.Type), member.Name));
                    } 
                }
            }
        }
 
        private bool AllowsMultiple(XamlMember member)
        { 
            return 
                member == XamlLanguage.Items ||
                member == XamlLanguage.PositionalParameters || 
                member == XamlLanguage.UnknownContent;
        }

        private XamlType GetCollectionTypeOnStack() 
        {
            Fx.Assert(_stack.TopFrame.Member == XamlLanguage.Items, "CollectionType should have _Items member"); 
            XamlType result; 
            if (_stack.FrameAtDepth(_stack.Depth - 1).FrameType == XamlStackFrameType.GetObject)
            { 
                XamlMember member = _stack.FrameAtDepth(_stack.Depth - 2).Member;
                if (member.IsUnknown)
                {
                    return null; 
                }
                result = member.Type; 
            } 
            else
            { 
                result = _stack.FrameAtDepth(_stack.Depth - 1).Type;
            }
            Fx.Assert(result.IsUnknown || result.IsCollection || result.IsDictionary,
                "Incorrect Collection Type Encountered"); 
            return result;
        } 
 
        private void ValidateUnknown(XamlMember member)
        { 
            if (member == XamlLanguage.UnknownContent)
            {
                ValidationError(SR.MemberUnknownContect(GetXamlTypeName(_stack.TopFrame.Type)));
            } 
            else if (member.IsUnknown)
            { 
                bool retryAttachable = false; 
                XamlType declaringType = member.DeclaringType;
                if (_stack.Depth == 1 && declaringType.IsUnknown && 
                    !string.IsNullOrEmpty(this.rootNamespace) &&
                    this.definedType != null && declaringType.Name == this.definedType.Name)
                {
                    // Need to handle the case where the namespace of a member on the document root 
                    // is missing the project root namespace
                    string clrNs; 
                    if (XamlBuildTaskServices.TryExtractClrNs(declaringType.PreferredXamlNamespace, out clrNs)) 
                    {
                        clrNs = string.IsNullOrEmpty(clrNs) ? this.rootNamespace : this.rootNamespace + "." + clrNs; 
                        if (clrNs == this.definedType.Namespace)
                        {
                            declaringType = SchemaContext.GetXamlType(this.definedType);
                            retryAttachable = true; 
                        }
                    } 
                } 
                XamlMember typeMember = declaringType.GetMember(member.Name);
                if (typeMember == null && retryAttachable) 
                {
                    typeMember = declaringType.GetAttachableMember(member.Name);
                }
                if (typeMember == null || typeMember.IsUnknown) 
                {
                    if (member.IsAttachable) 
                    { 
                        ValidationError(SR.UnresolvedAttachableMember(GetXamlTypeName(member.DeclaringType) + "." + member.Name));
                    } 
                    else if (member.IsDirective)
                    {
                        ValidationError(SR.UnresolvedDirective(member.PreferredXamlNamespace + ":" + member.Name));
                    } 
                    else
                    { 
                        // Skip if declaring type is unknown as the member unknown error messages become redundant. 
                        if (declaringType != null && !declaringType.IsUnknown)
                        { 
                            ValidationError(SR.UnresolvedMember(member.Name, GetXamlTypeName(declaringType)));
                        }
                    }
                } 
            }
        } 
 
        private void ValidateUnknown(XamlType type)
        { 
            if (type.IsUnknown)
            {
                if (type.IsGeneric)
                { 
                    ThrowGenericTypeValidationError(type);
                } 
                else 
                {
                    ThrowTypeValidationError(type); 
                }
            }
        }
 
        private void ThrowGenericTypeValidationError(XamlType type)
        { 
            IList unresolvedLeafTypeList = new List(); 
            XamlBuildTaskServices.GetUnresolvedLeafTypeArg(type, ref unresolvedLeafTypeList);
            if (unresolvedLeafTypeList.Count > 1 || !unresolvedLeafTypeList.Contains(type)) 
            {
                string fullTypeName = GetXamlTypeName(type);
                ValidationError(SR.UnresolvedGenericType(fullTypeName));
                foreach (XamlType xamlType in unresolvedLeafTypeList) 
                {
                    ThrowTypeValidationError(xamlType); 
                } 
            }
            else 
            {
                ThrowTypeValidationError(type);
            }
        } 

        private void ThrowTypeValidationError(XamlType type) 
        { 
            string typeName, assemblyName, ns;
            if (XamlBuildTaskServices.GetTypeNameInAssemblyOrNamespace(type, this.localAssemblyName, this.realAssemblyName, out typeName, out assemblyName, out ns)) 
            {
                ValidationError(SR.UnresolvedTypeWithAssemblyName(ns + "." + typeName, assemblyName));
            }
            else 
            {
                ValidationError(SR.UnresolvedTypeWithNamespace(typeName, ns)); 
            } 
        }
 
        private string GetXamlTypeName(XamlType type)
        {
            return XamlBuildTaskServices.GetTypeName(type, this.localAssemblyName, this.realAssemblyName);
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

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