ClassImporter.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 / ClassImporter.cs / 1305376 / ClassImporter.cs

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

namespace Microsoft.Build.Tasks.Xaml 
{
    using System; 
    using System.Collections.Generic; 
    using System.Diagnostics;
    using System.Globalization; 
    using System.Linq;
    using System.Xaml;
    using System.Xaml.Schema;
    using System.ComponentModel; 
    using System.Runtime;
    using System.Windows.Markup; 
 
    class ClassImporter
    { 
        string DefaultClassVisibility;
        string DefaultFieldVisibility;
        IExceptionLogger buildLogger;
        string xamlFileName; 
        string localAssemblyName;
        string rootNamespace; 
        NamespaceTable namespaceTable; 

        public ClassImporter(IExceptionLogger buildLogger, string xamlFileName, string localAssemblyName, string rootNamespace) 
        {
            this.buildLogger = buildLogger;
            this.xamlFileName = xamlFileName;
            this.localAssemblyName = localAssemblyName; 
            this.rootNamespace = rootNamespace;
            this.DefaultClassVisibility = XamlBuildTaskServices.PublicClassModifier; 
            this.DefaultFieldVisibility = XamlBuildTaskServices.InternalClassModifier; 
            this.namespaceTable = new NamespaceTable(localAssemblyName);
        } 

        // Throws InvalidOperationException at DesignTime: Input XAML contains invalid constructs for generating a class. For example, unexpected content or unknown class or field modifiers.
        public ClassData ReadFromXaml(XamlNodeList nodes)
        { 
            if (nodes == null)
            { 
                throw FxTrace.Exception.ArgumentNull("nodeList"); 
            }
 
            Stack currentTypes = new Stack();
            XamlReader reader = nodes.GetReader();
            XamlSchemaContext xsc = reader.SchemaContext;
            XamlNodeList strippedXamlNodes = new XamlNodeList(xsc); 
            XamlWriter strippedXamlNodesWriter = strippedXamlNodes.Writer;
 
            ClassData result = new ClassData() 
                {
                    FileName = this.xamlFileName, 
                    Visibility = DefaultClassVisibility,
                    RootNamespace = this.rootNamespace
                };
 
            // We loop through the provided XAML; for each node, we do two things:
            //  1. If it's a directive that's relevant to x:Class, we extract the data. 
            //  2. Unless it's a directive that's exclusively relevant to x:Class, we write it to strippedXamlNodes. 
            // The result is two outputs: class data, and stripped XAML that can be used to initialize the
            // an instance of the class. 

            bool readNextNode = false;
            while (readNextNode || reader.Read())
            { 
                bool stripNodeFromXaml = false;
                readNextNode = false; 
 
                namespaceTable.ManageNamespace(reader);
 
                switch (reader.NodeType)
                {
                    case XamlNodeType.StartObject:
                        if (result.RootTypeName == null) 
                        {
                            result.RootTypeName = reader.Type; 
                        } 
                        currentTypes.Push(new NamedObject()
                            { 
                                TypeName = reader.Type,
                                Visibility = DefaultFieldVisibility,
                                TypeArguments = reader.Type.TypeArguments,
                            }); 
                        break;
 
                    case XamlNodeType.EndObject: 
                        currentTypes.Pop();
                        break; 

                    case XamlNodeType.StartMember:
                        XamlMember member = reader.Member;
 
                        if (member.IsDirective)
                        { 
                            bool isRootElement = (currentTypes.Count == 1); 
                            stripNodeFromXaml = ProcessDirective(reader, result, currentTypes.Peek(), isRootElement, strippedXamlNodes, out readNextNode);
                        } 
                        else
                        {
                            NamedObject currentType = currentTypes.Peek();
                            XamlType currentXamlType = currentType.TypeName; 
                            if (currentXamlType.IsUnknown)
                            { 
                                result.RequiresCompilationPass2 = true; 
                            }
                        } 
                        break;

                    case XamlNodeType.EndMember:
                        break; 

                    case XamlNodeType.Value: 
                        break; 

                    case XamlNodeType.NamespaceDeclaration: 
                        break;

                    case XamlNodeType.None:
                        break; 

                    case XamlNodeType.GetObject: 
                        //Push a dummy NamedObject so that it gets popped when you see the corresponding EndObject 
                        currentTypes.Push(new NamedObject());
                        break; 

                    default:

                        Debug.Fail("Unrecognized XamlNodeType value" + reader.NodeType.ToString()); 
                        break;
                } 
 
                if (!stripNodeFromXaml)
                { 
                    WritestrippedXamlNode(reader, strippedXamlNodesWriter);
                }
            }
 
            // ClassData.Name should be initialized to a non-null non-empty value if
            // the file contains x:Class. Throw an error if neither is found. 
            if (result.Name == null) 
            {
                string xClassDirectiveName = "{" + XamlLanguage.Class.PreferredXamlNamespace + "}" + XamlLanguage.Class.Name; 

                throw FxTrace.Exception.AsError(LogInvalidOperationException(null, SR.TaskCannotProcessFileWithoutType(xClassDirectiveName)));
            }
 
            strippedXamlNodes.Writer.Close();
            strippedXamlNodes = RewriteRootNode(strippedXamlNodes, result.Name, result.Namespace); 
 
            result.StrippedXaml = strippedXamlNodes;
            return result; 
        }

        IList UpdateTypeArgs(IList typeArgs, XamlSchemaContext xsc)
        { 
            if (typeArgs != null)
            { 
                IList updatedTypeArgs = new List(); 
                foreach (var typeArg in typeArgs)
                { 
                    IList typeArgTypeArgs = UpdateTypeArgs(typeArg.TypeArguments, xsc);
                    string typeArgXmlns = XamlBuildTaskServices.UpdateClrNamespaceUriWithLocalAssembly(typeArg.PreferredXamlNamespace, this.localAssemblyName);
                    updatedTypeArgs.Add(new XamlType(typeArgXmlns, typeArg.Name, typeArgTypeArgs, xsc));
                } 
                return updatedTypeArgs;
            } 
            return typeArgs; 
        }
 
        void WritestrippedXamlNode(XamlReader reader, XamlWriter writer)
        {
            switch (reader.NodeType)
            { 
                case XamlNodeType.StartObject:
                    XamlType xamlType = reader.Type; 
                    if (xamlType.IsUnknown) 
                    {
                        IList typeArgs = UpdateTypeArgs(xamlType.TypeArguments, reader.SchemaContext); 
                        string xmlns = XamlBuildTaskServices.UpdateClrNamespaceUriWithLocalAssembly(xamlType.PreferredXamlNamespace, this.localAssemblyName);
                        xamlType = new XamlType(xmlns, xamlType.Name, typeArgs, reader.SchemaContext);
                    }
                    writer.WriteStartObject(xamlType); 
                    break;
 
                case XamlNodeType.StartMember: 
                    XamlMember member = reader.Member;
                    if (member.IsUnknown && !member.IsDirective) 
                    {
                        string xmlns = XamlBuildTaskServices.UpdateClrNamespaceUriWithLocalAssembly(member.DeclaringType.PreferredXamlNamespace, this.localAssemblyName);
                        XamlType memberXamlType = new XamlType(xmlns, member.DeclaringType.Name, member.DeclaringType.TypeArguments, reader.SchemaContext);
                        member = new XamlMember(member.Name, memberXamlType, member.IsAttachable); 
                    }
                    writer.WriteStartMember(member); 
                    break; 

                case XamlNodeType.NamespaceDeclaration: 
                    NamespaceDeclaration ns = new NamespaceDeclaration(
                        XamlBuildTaskServices.UpdateClrNamespaceUriWithLocalAssembly(reader.Namespace.Namespace, this.localAssemblyName),
                        reader.Namespace.Prefix);
                    writer.WriteNamespace(ns); 
                    break;
 
                case XamlNodeType.GetObject: 
                case XamlNodeType.EndObject:
                case XamlNodeType.EndMember: 
                case XamlNodeType.Value:
                case XamlNodeType.None:
                    writer.WriteNode(reader);
                    break; 

                default: 
                    Debug.Fail("Unrecognized XamlNodeType value" + reader.NodeType.ToString()); 
                    break;
            } 
        }

        XamlNodeList RewriteRootNode(XamlNodeList strippedXamlNodes, string name, string @namespace)
        { 
            // Rewrite the root node to have the name of class declared via x:Class (rather than the base class)
            // Also, for any properties on the root object that are declared in this class, need to rewrite the 
            // namespace to include the root namespace, if there is one. 

            string oldNamespace = null; 
            if (!string.IsNullOrEmpty(this.rootNamespace))
            {
                oldNamespace = @namespace;
                if (!string.IsNullOrEmpty(@namespace)) 
                {
                    @namespace = this.rootNamespace + "." + @namespace; 
                } 
                else
                { 
                    @namespace = this.rootNamespace;
                }
            }
 
            string namespaceName = string.Format(CultureInfo.InvariantCulture, "{0}{1};{2}{3}", XamlBuildTaskServices.ClrNamespaceUriNamespacePart, @namespace, XamlBuildTaskServices.ClrNamespaceUriAssemblyPart, this.localAssemblyName);
 
            XamlReader reader = strippedXamlNodes.GetReader(); 
            XamlSchemaContext xsc = reader.SchemaContext;
            XamlNodeList newStrippedXamlNodes = new XamlNodeList(xsc); 
            XamlWriter writer = newStrippedXamlNodes.Writer;

            int depth = 0;
            XamlType rootXamlType = null; 
            while (reader.Read())
            { 
                switch (reader.NodeType) 
                {
                    case XamlNodeType.StartObject: 
                    case XamlNodeType.GetObject:
                        depth++;
                        break;
                    case XamlNodeType.EndObject: 
                        depth--;
                        break; 
                } 
                if (reader.NodeType == XamlNodeType.StartObject && depth == 1)
                { 
                    rootXamlType = new XamlType(namespaceName, name, null, xsc);
                    writer.WriteStartObject(rootXamlType);
                }
                else if (reader.NodeType == XamlNodeType.StartMember && depth == 1 && reader.Member.IsUnknown 
                    && reader.Member.DeclaringType != null && reader.Member.DeclaringType.Name == rootXamlType.Name)
                { 
                    string clrNs; 
                    XamlMember member = reader.Member;
                    if (XamlBuildTaskServices.TryExtractClrNs(member.PreferredXamlNamespace, out clrNs) && 
                        clrNs == oldNamespace)
                    {
                        // This is a member defined on the document root type, but missing the project root namespace. Fix it.
                        XamlMember newMember = new XamlMember(member.Name, rootXamlType, member.IsAttachable); 
                        Fx.Assert(rootXamlType != null, "First StartObject should already have been processed");
                        writer.WriteStartMember(newMember); 
                    } 
                    else
                    { 
                        writer.WriteNode(reader);
                    }
                }
                else 
                {
                    writer.WriteNode(reader); 
                } 
            }
 
            writer.Close();
            return newStrippedXamlNodes;
        }
 
        bool ProcessDirective(XamlReader reader, ClassData classData,
            NamedObject currentObject, bool isRootElement, XamlNodeList strippedXamlNodes, out bool readNextNode) 
        { 
            Fx.Assert(reader.NodeType == XamlNodeType.StartMember, "Current node should be a Start Member Node");
 
            XamlMember member = reader.Member;
            bool directiveRecognized = false;
            readNextNode = false;
 
            switch (member.Name)
            { 
                case "Name": 
                    // Unlike all the other directives that we process, x:Name should be written
                    // to the stripped output. 
                    strippedXamlNodes.Writer.WriteStartMember(member);

                    string objectName = ReadAtom(reader, XamlLanguage.Name.Name);
                    if (!objectName.StartsWith(XamlBuildTaskServices.SerializerReferenceNamePrefix, 
                        StringComparison.Ordinal))
                    { 
                        currentObject.Name = objectName; 
                        classData.NamedObjects.Add(currentObject);
                    } 

                    strippedXamlNodes.Writer.WriteValue(objectName);
                    strippedXamlNodes.Writer.WriteEndMember();
                    directiveRecognized = true; 
                    break;
 
                case "Class": 
                    if (isRootElement)
                    { 
                        string fullClassName = ReadAtom(reader, XamlLanguage.Class.Name);
                        SetClassName(fullClassName, classData);
                        directiveRecognized = true;
                    } 
                    break;
 
                case "ClassModifier": 
                    if (isRootElement)
                    { 
                        classData.Visibility = ReadAtom(reader, XamlLanguage.ClassModifier.Name);
                        directiveRecognized = true;
                    }
                    break; 

                case "FieldModifier": 
                    currentObject.Visibility = ReadAtom(reader, XamlLanguage.FieldModifier.Name); 
                    directiveRecognized = true;
                    break; 

                case "Code":
                    string codeSnippet = ReadAtom(reader, XamlLanguage.Code.Name);
                    classData.CodeSnippets.Add(codeSnippet); 
                    directiveRecognized = true;
                    break; 
 
                case "TypeArguments":
                    if (isRootElement) 
                    {
                        classData.TypeArguments = currentObject.TypeArguments;
                        SkipOneLess(reader);
                        directiveRecognized = true; 
                    }
                    break; 
 
                case "Members":
                    classData.Members = ReadMembersCollection(reader.ReadSubtree()); 
                    if (!classData.RequiresCompilationPass2)
                    {
                        foreach (PropertyDefinition property in classData.Members.Values)
                        { 
                            if (property.Type.IsUnknown)
                            { 
                                classData.RequiresCompilationPass2 = true; 
                                break;
                            } 
                        }
                    }
                    directiveRecognized = true;
                    readNextNode = true; 
                    break;
 
                case "ClassAttributes": 
                    classData.Attributes = ReadAttributesCollection(reader.ReadSubtree());
                    directiveRecognized = true; 
                    readNextNode = true;
                    break;

            } 

            if (directiveRecognized == true && readNextNode == false) 
            { 
                reader.Read();
                Fx.Assert(reader.NodeType == XamlNodeType.EndMember, "Current node should be a XamlEndmember"); 
            }

            return directiveRecognized;
        } 

        private IList ReadAttributesCollection(XamlReader reader) 
        { 
            IList attributes = new List();
            bool nextNodeRead = false; 
            while (nextNodeRead || reader.Read())
            {
                this.namespaceTable.ManageNamespace(reader);
                nextNodeRead = false; 
                if (reader.NodeType == XamlNodeType.StartObject && reader.Type != null)
                { 
                    AttributeData attribute = null; 
                    try
                    { 
                        attribute = AttributeData.LoadAttributeData(reader.ReadSubtree(), this.namespaceTable, this.rootNamespace);
                    }
                    catch (InvalidOperationException e)
                    { 
                        throw FxTrace.Exception.AsError(LogInvalidOperationException(reader, e.Message));
                    } 
                    nextNodeRead = true; 
                    attributes.Add(attribute);
                } 
            }

            return attributes;
        } 

        IDictionary ReadMembersCollection(XamlReader reader) 
        { 
            IDictionary members = new Dictionary();
 
            bool nextNodeRead = false;
            while (nextNodeRead || reader.Read())
            {
                namespaceTable.ManageNamespace(reader); 
                nextNodeRead = false;
                if (reader.NodeType == XamlNodeType.StartObject) 
                { 
                    if (reader.Type == XamlLanguage.Property)
                    { 
                        PropertyDefinition xProperty = LoadProperty(reader.ReadSubtree());
                        nextNodeRead = true;
                        if (members.ContainsKey(xProperty.Name))
                        { 
                            throw FxTrace.Exception.AsError(LogInvalidOperationException(reader, SR.DuplicatePropertyDefinition(xProperty.Name)));
                        } 
                        members.Add(xProperty.Name, xProperty); 
                    }
                } 
            }

            return members;
        } 

        PropertyDefinition LoadProperty(XamlReader xamlReader) 
        { 
            if (xamlReader == null)
            { 
                throw FxTrace.Exception.ArgumentNull("xamlReader");
            }

            PropertyDefinition property = new PropertyDefinition(); 
            while (xamlReader.Read())
            { 
                if (xamlReader.NodeType == XamlNodeType.StartMember) 
                {
                    XamlMember member = xamlReader.Member; 
                    switch(member.Name)
                    {
                        case "Name":
                            property.Name = ReadValueAsString(xamlReader.ReadSubtree()); 
                            break;
                        case "Type": 
                            property.Type = ReadPropertyType(xamlReader.ReadSubtree()); 
                            break;
                        case "Attributes": 
                            ((List)property.Attributes).AddRange(ReadAttributesCollection(xamlReader.ReadSubtree()));
                            break;
                        case "Modifier":
                            property.Modifier = ReadValueAsString(xamlReader.ReadSubtree()); 
                            break;
                        default: 
                            throw FxTrace.Exception.AsError(LogInvalidOperationException(xamlReader, SR.UnknownPropertyMember(member.Name))); 
                    }
                } 
            }
            if (string.IsNullOrEmpty(property.Name))
            {
                throw FxTrace.Exception.AsError(LogInvalidOperationException(xamlReader, SR.PropertyNameRequired)); 
            }
            if (property.Type == null) 
            { 
                throw FxTrace.Exception.AsError(LogInvalidOperationException(xamlReader, SR.PropertyTypeRequired(property.Name)));
            } 
            return property;
        }

        XamlType ReadPropertyType(XamlReader xamlReader) 
        {
            while (xamlReader.Read()) 
            { 
                if (xamlReader.NodeType == XamlNodeType.Value && xamlReader.Value is string)
                { 
                    return XamlBuildTaskServices.GetXamlTypeFromString((string)xamlReader.Value, this.namespaceTable, xamlReader.SchemaContext);
                }
            }
            return null; 
        }
 
        string ReadValueAsString(XamlReader xamlReader) 
        {
            while (xamlReader.Read()) 
            {
                if (xamlReader.NodeType == XamlNodeType.Value)
                {
                    return xamlReader.Value as string; 
                }
            } 
            return string.Empty; 
        }
 
        string ReadAtom(XamlReader reader, string propertyName)
        {
            reader.Read();
            if (reader.NodeType != XamlNodeType.Value) 
            {
                throw FxTrace.Exception.AsError(LogInvalidOperationException(reader, SR.TextRepresentationExpected(propertyName))); 
            } 
            return (string)reader.Value;
        } 

        void SetClassName(string fullClassName, ClassData classData)
        {
            int lastIndex = fullClassName.LastIndexOf('.'); 
            if (lastIndex != -1)
            { 
                string classNamespace = fullClassName.Substring(0, lastIndex); 
                string className = fullClassName.Substring(lastIndex + 1);
 
                classData.Name = className;
                classData.Namespace = classNamespace;
            }
            else 
            {
                classData.Name = fullClassName; 
                classData.Namespace = String.Empty; 
            }
 
            if (string.IsNullOrEmpty(classData.Name))
            {
                throw FxTrace.Exception.AsError(LogInvalidOperationException(null, SR.ClassNameMustBeNonEmpty));
            } 
        }
 
        int SkipOneLess(XamlReader reader) 
        {
            Fx.Assert(reader != null, "reader parameter should never be null"); 
            int nodeCount = 0;
            if (reader.NodeType == XamlNodeType.Value)
            {
                reader.Read(); 
                nodeCount++;
                return nodeCount; 
            } 

            int depth = 1; 
            while (depth > 0)
            {
                if (reader.IsEof)
                { 
                    throw FxTrace.Exception.AsError(LogInvalidOperationException(null, SR.UnexpectedEndOfXaml));
                } 
                reader.Read(); 
                nodeCount++;
 
                switch (reader.NodeType)
                {
                    case XamlNodeType.StartMember:
                    case XamlNodeType.StartObject: 
                        depth++;
                        break; 
 
                    case XamlNodeType.EndMember:
                    case XamlNodeType.EndObject: 
                        depth--;
                        break;
                }
            } 
            return nodeCount;
        } 
 
        Exception LogInvalidOperationException(XamlReader reader, string exceptionMessage)
        { 
            IXamlLineInfo lineInfo = reader == null ? null : reader as IXamlLineInfo;
            if (lineInfo != null && lineInfo.HasLineInfo)
            {
                return this.buildLogger.LogException( 
                    new InvalidOperationException(exceptionMessage),
                    this.xamlFileName, 
                    lineInfo.LineNumber, 
                    lineInfo.LinePosition);
            } 
            else
            {
                return this.buildLogger.LogException(
                    new InvalidOperationException(exceptionMessage), 
                    this.xamlFileName);
            } 
        } 
    }
} 

// 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