示例#1
0
        static void Demo4(CodeCompileUnit ccu)
        {
            // create one of these lil guys
            var res = new CodeDomResolver();

            // add our code to it
            res.CompileUnits.Add(ccu);
            // give it a chance to build its information over our code
            res.Refresh();
            CodeDomVisitor.Visit(ccu, (ctx) => {
                // for every expression...
                var expr = ctx.Target as CodeExpression;
                if (null != expr)
                {
                    // except method reference expressions...
                    var mri = expr as CodeMethodReferenceExpression;
                    if (null != mri)
                    {
                        return;
                    }
                    // get the expression type
                    var type = res.TryGetTypeOfExpression(expr);
                    // write it along with the expression itself
                    Console.WriteLine(
                        "Expression type {0}: {1} is {2}",
                        expr.GetType().Name,
                        CodeDomUtility.ToString(expr),
                        null != type?CodeDomUtility.ToString(type):"unresolvable");
                }
            });
            Console.WriteLine("Press any key...");
            Console.ReadKey();
            Console.Clear();
        }
示例#2
0
        /// <summary>
        /// Gets the next element that has not been resolved
        /// </summary>
        /// <param name="compileUnits">The compile units to search</param>
        /// <returns>A <see cref="CodeObject"/> representing the next code object that needs to be patched</returns>
        public static CodeObject GetNextUnresolvedElement(IEnumerable <CodeCompileUnit> compileUnits)
        {
            CodeObject result = null;

            foreach (var cu in compileUnits)
            {
                CodeDomVisitor.Visit(cu, (ctx) =>
                {
                    var co = ctx.Target as CodeObject;
                    if (null != co)
                    {
                        if (co.UserData.Contains("slang:unresolved"))
                        {
                            result     = co;
                            ctx.Cancel = true;
                        }
                    }
                });
                if (null != result)
                {
                    return(result);
                }
            }
            return(null);
        }
示例#3
0
        static void RunResolver()
        {
            byte[] data;
            using (var stream = File.OpenRead(@"myfile.bin"))
            {
                data = new byte[(int)stream.Length];
                stream.Read(data, 0, data.Length);
            }

            // create a resolver
            var res = new CodeDomResolver();

            // read the resolver sample into the compile unit
            CodeCompileUnit ccu;

            using (var stm = File.OpenRead(@"..\..\Resolver.cs"))
                ccu = SlangParser.ReadCompileUnitFrom(stm);

            // remember to patch it!
            SlangPatcher.Patch(ccu);

            Console.Error.WriteLine(CU.ToString(ccu));

            // add the compile unit to the resolver
            res.CompileUnits.Add(ccu);

            // prepare the resolver
            // any time you add compile units you'll need
            // to call Refresh()
            res.Refresh();

            // go through all expressions in the
            // graph and try to get their type
            CodeDomVisitor.Visit(ccu, (ctx) => {
                var expr = ctx.Target as CodeExpression;
                if (null != expr)
                {
                    // we want everything except CodeTypeReferenceExpression
                    var ctre = expr as CodeTypeReferenceExpression;
                    if (null == ctre)
                    {
                        // get the scope of the expression
                        var scope             = res.GetScope(expr);
                        CodeTypeReference ctr = res.TryGetTypeOfExpression(expr, scope);
                        if (null != ctr)
                        {
                            Console.WriteLine(CU.ToString(expr) + " is type: " + CU.ToString(ctr));
                            Console.WriteLine("Scope Dump:");
                            Console.WriteLine(scope.ToString());
                        }
                    }
                }
            });
        }
示例#4
0
        static void RunTemplate()
        {
            // compute the primes. algorithm borrowed
            // from SLax at https://stackoverflow.com/questions/1510124/program-to-find-prime-numbers
            var primesMax = 100;
            var primesArr = Enumerable.Range(0, (int)Math.Floor(2.52 * Math.Sqrt(primesMax) / Math.Log(primesMax))).Aggregate(
                Enumerable.Range(2, primesMax - 1).ToList(),
                (result, index) =>
            {
                var bp = result[index]; var sqr = bp * bp;
                result.RemoveAll(i => i >= sqr && i % bp == 0);
                return(result);
            }
                ).ToArray();

            // read the template into the compile unit
            CodeCompileUnit ccu;

            using (var stm = File.OpenRead(@"..\..\Template.cs"))
                ccu = SlangParser.ReadCompileUnitFrom(stm);

            // patch it either before or after modifying it
            SlangPatcher.Patch(ccu);

            // find the target namespace and change it
            var ns = ccu.TryGetNamespace("T_NAMESPACE");

            ns.Name = "TestNS";
            // find the target class
            var type = ns.TryGetType("T_TYPE");

            // change the name
            type.Name = "TestPrimes";
            // get the Primes field:
            var primes = type.TryGetMember("Primes") as CodeMemberField;

            // change the init expression to the primes array
            primes.InitExpression = CU.Literal(primesArr);

            // fixup any references to T_NAMESPACE or T_TYPE
            CodeDomVisitor.Visit(ccu, (ctx) => {
                var ctr = ctx.Target as CodeTypeReference;
                if (null != ctr)
                {
                    ctr.BaseType = ctr.BaseType.Replace("T_NAMESPACE", ns.Name).Replace("T_TYPE", type.Name);
                }
            });

            // already patched prior
            // SlangPatcher.Patch(ccu);

            // now write the result out
            Console.WriteLine(CU.ToString(ccu));
        }
 private static void _FillTypeMap(CodeNamespace codeNamespace, Dictionary <string, CodeTypeDeclaration> typeMap)
 {
     CodeDomVisitor.Visit(codeNamespace, (ctx) =>
     {
         var td = ctx.Target as CodeTypeDeclaration;
         if (null != td)
         {
             foreach (CodeAttributeDeclaration decl in td.CustomAttributes)
             {
                 if (0 == string.Compare("System.Xml.Serialization.XmlTypeAttribute", decl.AttributeType.BaseType, StringComparison.InvariantCulture))
                 {
                     typeMap.Add(td.Name, td);
                     break;
                 }
             }
         }
     }, CodeDomVisitTargets.Types);
 }
示例#6
0
        static bool _HasUnresolved(CodeObject target)
        {
            if (target.UserData.Contains("slang:unresolved"))
            {
                return(true);
            }
            var result = false;

            CodeDomVisitor.Visit(target, (ctx) =>
            {
                var co = ctx.Target as CodeObject;
                if (null != co && co.UserData.Contains("slang:unresolved"))
                {
                    result     = true;
                    ctx.Cancel = true;
                }
            });
            return(result);
        }
 private static void _FillPropFldMaps(CodeTypeDeclaration td, HashSet <string> propElem, HashSet <string> propAttr, Dictionary <string, string> fldMap)
 {
     CodeDomVisitor.Visit(td, (ctx) =>
     {
         var prop = ctx.Target as CodeMemberProperty;
         if (null != prop)
         {
             foreach (CodeAttributeDeclaration decl in prop.CustomAttributes)
             {
                 var isAttr = 0 == string.Compare("System.Xml.Serialization.XmlAttributeAttribute", decl.AttributeType.BaseType, StringComparison.InvariantCulture);
                 var isElem = !isAttr && 0 == string.Compare("System.Xml.Serialization.XmlElementAttribute", decl.AttributeType.BaseType, StringComparison.InvariantCulture);
                 if (isAttr || isElem)
                 {
                     if (0 < prop.GetStatements.Count)
                     {
                         var mr = prop.GetStatements[0] as CodeMethodReturnStatement;
                         if (null != mr)
                         {
                             var fr = mr.Expression as CodeFieldReferenceExpression;
                             if (null != fr)
                             {
                                 fldMap.Add(fr.FieldName, prop.Name);
                                 if (isElem)
                                 {
                                     propElem.Add(prop.Name);
                                 }
                                 if (isAttr)
                                 {
                                     propAttr.Add(prop.Name);
                                 }
                             }
                         }
                     }
                     break;
                 }
             }
         }
     }, CodeDomVisitTargets.Types | CodeDomVisitTargets.Members);
 }
        /// <summary>
        /// Patches the CodeDOM tree received from the <see cref="SlangParser"/> into something more usable, by resolving type information and replacing various elements in the CodeDOM graph
        /// </summary>
        /// <param name="compileUnits">The <see cref="CodeCompileUnit"/> objects to patch</param>
        public static void Patch(IEnumerable <CodeCompileUnit> compileUnits)
        {
            var resolver = new CodeDomResolver();

            foreach (var ccu in compileUnits)
            {
                resolver.CompileUnits.Add(ccu);
            }
            resolver.Refresh();
            var working  = -1;
            var oworking = 0;

            while (0 != working && oworking != working)
            {
                oworking = working;
                working  = 0;
                for (int ic = resolver.CompileUnits.Count, i = 0; i < ic; ++i)
                {
                    CodeDomVisitor.Visit(resolver.CompileUnits[i], (ctx) => {
                        var co = ctx.Target as CodeObject;
                        if (null != co && co.UserData.Contains("slang:unresolved"))
                        {
                            ++working;
                            _Patch(ctx.Target as CodeFieldReferenceExpression, ctx, resolver);
                            _Patch(ctx.Target as CodeVariableDeclarationStatement, ctx, resolver);
                            _Patch(ctx.Target as CodeVariableReferenceExpression, ctx, resolver);
                            _Patch(ctx.Target as CodeDelegateInvokeExpression, ctx, resolver);
                            _Patch(ctx.Target as CodeObjectCreateExpression, ctx, resolver);
                            _Patch(ctx.Target as CodeIndexerExpression, ctx, resolver);
                            _Patch(ctx.Target as CodeMemberMethod, ctx, resolver);
                            _Patch(ctx.Target as CodeMemberProperty, ctx, resolver);
                            _Patch(ctx.Target as CodeTypeReference, ctx, resolver);
                        }
                    });
                }
                resolver.Refresh();
            }
        }
示例#9
0
 static void Demo3(CodeCompileUnit ccu)
 {
     /// now let's take our code and modify it
     CodeDomVisitor.Visit(ccu, (ctx) => {
         // we're looking for a method invocation
         var mi = ctx.Target as CodeMethodInvokeExpression;
         if (null != mi)
         {
             // ... calling WriteLine
             if ("WriteLine" == mi.Method?.MethodName)
             {
                 // replace the passed in expression with "Hello world!"
                 mi.Parameters.Clear();
                 mi.Parameters.Add(new CodePrimitiveExpression("Hello world!"));
                 // done after the first WriteLine so we cancel
                 ctx.Cancel = true;
             }
         }
     });
     Console.WriteLine(CodeDomUtility.ToString(ccu));
     Console.WriteLine("Press any key...");
     Console.ReadKey();
     Console.Clear();
 }
示例#10
0
        public static int Run(string[] args, TextReader stdin, TextWriter stdout, TextWriter stderr)
        {
            // our return code
            var result = 0;
            // app parameters
            string inputfile     = null;
            string outputfile    = null;
            string codeclass     = null;
            string codelanguage  = null;
            string codenamespace = null;
            string externaltoken = null;
            string nfagraph      = null;
            string dfagraph      = null;
            bool   ignorecase    = false;
            bool   noshared      = false;
            bool   ifstale       = false;
            // our working variables
            TextReader input  = null;
            TextWriter output = null;

            try
            {
                if (0 == args.Length)
                {
                    _PrintUsage(stderr);
                    result = -1;
                }
                else if (args[0].StartsWith("/"))
                {
                    throw new ArgumentException("Missing input file.");
                }
                else
                {
                    // process the command line args
                    inputfile = args[0];
                    for (var i = 1; i < args.Length; ++i)
                    {
                        switch (args[i].ToLowerInvariant())
                        {
                        case "/output":
                            if (args.Length - 1 == i)                                     // check if we're at the end
                            {
                                throw new ArgumentException(string.Format("The parameter \"{0}\" is missing an argument", args[i].Substring(1)));
                            }
                            ++i;                                     // advance
                            outputfile = args[i];
                            break;

                        case "/class":
                            if (args.Length - 1 == i)                                     // check if we're at the end
                            {
                                throw new ArgumentException(string.Format("The parameter \"{0}\" is missing an argument", args[i].Substring(1)));
                            }
                            ++i;                                     // advance
                            codeclass = args[i];
                            break;

                        case "/language":
                            if (args.Length - 1 == i)                                     // check if we're at the end
                            {
                                throw new ArgumentException(string.Format("The parameter \"{0}\" is missing an argument", args[i].Substring(1)));
                            }
                            ++i;                                     // advance
                            codelanguage = args[i];
                            break;

                        case "/namespace":
                            if (args.Length - 1 == i)                                     // check if we're at the end
                            {
                                throw new ArgumentException(string.Format("The parameter \"{0}\" is missing an argument", args[i].Substring(1)));
                            }
                            ++i;                                     // advance
                            codenamespace = args[i];
                            break;

                        case "/external":
                            if (args.Length - 1 == i)                                     // check if we're at the end
                            {
                                throw new ArgumentException(string.Format("The parameter \"{0}\" is missing an argument", args[i].Substring(1)));
                            }
                            ++i;                                     // advance
                            externaltoken = args[i];
                            break;

                        case "/nfagraph":
                            if (args.Length - 1 == i)                                     // check if we're at the end
                            {
                                throw new ArgumentException(string.Format("The parameter \"{0}\" is missing an argument", args[i].Substring(1)));
                            }
                            ++i;                                     // advance
                            nfagraph = args[i];
                            break;

                        case "/dfagraph":
                            if (args.Length - 1 == i)                                     // check if we're at the end
                            {
                                throw new ArgumentException(string.Format("The parameter \"{0}\" is missing an argument", args[i].Substring(1)));
                            }
                            ++i;                                     // advance
                            dfagraph = args[i];
                            break;

                        case "/ignorecase":
                            ignorecase = true;
                            break;

                        case "/noshared":
                            noshared = true;
                            break;

                        case "/ifstale":
                            ifstale = true;
                            break;


                        default:
                            throw new ArgumentException(string.Format("Unknown switch {0}", args[i]));
                        }
                    }
                    // now build it
                    if (string.IsNullOrEmpty(codeclass))
                    {
                        // default we want it to be named after the code file
                        // otherwise we'll use inputfile
                        if (null != outputfile)
                        {
                            codeclass = Path.GetFileNameWithoutExtension(outputfile);
                        }
                        else
                        {
                            codeclass = Path.GetFileNameWithoutExtension(inputfile);
                        }
                    }
                    if (string.IsNullOrEmpty(codelanguage))
                    {
                        if (!string.IsNullOrEmpty(outputfile))
                        {
                            codelanguage = Path.GetExtension(outputfile);
                            if (codelanguage.StartsWith("."))
                            {
                                codelanguage = codelanguage.Substring(1);
                            }
                        }
                        if (string.IsNullOrEmpty(codelanguage))
                        {
                            codelanguage = "cs";
                        }
                    }
                    var stale = true;
                    if (ifstale && null != outputfile)
                    {
                        stale = _IsStale(inputfile, outputfile);
                        if (!stale)
                        {
                            stale = _IsStale(CodeBase, outputfile);
                        }
                    }
                    if (!stale)
                    {
                        stderr.WriteLine("{0} skipped building {1} because it was not stale.", Name, outputfile);
                    }
                    else
                    {
                        if (null != outputfile)
                        {
                            stderr.Write("{0} is building file: {1}", Name, outputfile);
                        }
                        else
                        {
                            stderr.Write("{0} is building tokenizer.", Name);
                        }
                        input = new StreamReader(inputfile);
                        var    rules = new List <LexRule>();
                        string line;
                        while (null != (line = input.ReadLine()))
                        {
                            var lc = LexContext.Create(line);
                            lc.TrySkipCCommentsAndWhiteSpace();
                            if (-1 != lc.Current)
                            {
                                rules.Add(LexRule.Parse(lc));
                            }
                        }
                        input.Close();
                        input = null;
                        LexRule.FillRuleIds(rules);

                        var ccu = new CodeCompileUnit();
                        var cns = new CodeNamespace();
                        if (!string.IsNullOrEmpty(codenamespace))
                        {
                            cns.Name = codenamespace;
                        }
                        ccu.Namespaces.Add(cns);
                        var fa          = _BuildLexer(rules, ignorecase, inputfile);
                        var symbolTable = _BuildSymbolTable(rules);
                        var symids      = new int[symbolTable.Length];
                        for (var i = 0; i < symbolTable.Length; ++i)
                        {
                            symids[i] = i;
                        }
                        var blockEnds = _BuildBlockEnds(rules);
                        var nodeFlags = _BuildNodeFlags(rules);
                        if (null != nfagraph)
                        {
                            fa.RenderToFile(nfagraph);
                        }

                        fa = fa.ToDfa();
                        DfaEntry[] dfaTable = null;
                        dfaTable = _ToDfaStateTable(fa, symids);
                        if (!noshared)
                        {
                            if (string.IsNullOrEmpty(externaltoken))
                            {
                                // import our Export/Token.cs into the library
                                _ImportCompileUnit(Deslanged.Token, cns);
                            }

                            // import our Export/TableTokenizer.cs into the library
                            _ImportCompileUnit(Deslanged.TableTokenizer, cns);
                        }
                        if (!string.IsNullOrEmpty(externaltoken))
                        {
                            cns.Imports.Add(new CodeNamespaceImport(externaltoken));
                        }
                        var origName           = "Rolex.";
                        CodeTypeDeclaration td = null;
                        if (null == td)
                        {
                            td        = Deslanged.TableTokenizerTemplate.Namespaces[1].Types[0];
                            origName += td.Name;
                            td.Name   = codeclass;
                            CodeGenerator.GenerateSymbolConstants(td, symbolTable);
                        }
                        CodeDomVisitor.Visit(td, (ctx) =>
                        {
                            var tr = ctx.Target as CodeTypeReference;
                            if (null != tr)
                            {
                                if (0 == string.Compare(origName, tr.BaseType, StringComparison.InvariantCulture))
                                {
                                    tr.BaseType = codeclass;
                                }
                            }
                        });
                        CodeMemberField f = null;

                        f = CodeDomUtility.GetByName("DfaTable", td.Members) as CodeMemberField;
                        f.InitExpression = CodeGenerator.GenerateDfaTableInitializer(dfaTable);

                        f = CodeDomUtility.GetByName("NodeFlags", td.Members) as CodeMemberField;
                        f.InitExpression = CodeDomUtility.Literal(nodeFlags);
                        f = CodeDomUtility.GetByName("BlockEnds", td.Members) as CodeMemberField;
                        f.InitExpression = CodeDomUtility.Literal(blockEnds);

                        cns.Types.Add(td);

                        var hasColNS = false;
                        foreach (CodeNamespaceImport nsi in cns.Imports)
                        {
                            if (0 == string.Compare(nsi.Namespace, "System.Collections.Generic", StringComparison.InvariantCulture))
                            {
                                hasColNS = true;
                                break;
                            }
                        }
                        if (!hasColNS)
                        {
                            cns.Imports.Add(new CodeNamespaceImport("System.Collections.Generic"));
                        }

                        stderr.WriteLine();
                        var prov = CodeDomProvider.CreateProvider(codelanguage);
                        var opts = new CodeGeneratorOptions();
                        opts.BlankLinesBetweenMembers = false;
                        opts.VerbatimOrder            = true;
                        if (null == outputfile)
                        {
                            output = stdout;
                        }
                        else
                        {
                            // open the file and truncate it if necessary
                            var stm = File.Open(outputfile, FileMode.Create);
                            stm.SetLength(0);
                            output = new StreamWriter(stm);
                        }
                        prov.GenerateCodeFromCompileUnit(ccu, output, opts);
                    }
                }
            }
            // we don't like to catch in debug mode
#if !DEBUG
            catch (Exception ex)
            {
                result = _ReportError(ex, stderr);
            }
#endif
            finally
            {
                // close the input file if necessary
                if (null != input)
                {
                    input.Close();
                }
                // close the output file if necessary
                if (null != outputfile && null != output)
                {
                    output.Close();
                }
            }
            return(result);
        }
示例#11
0
        static void _Patch(CodeVariableReferenceExpression vr, CodeDomVisitContext ctx, CodeDomResolver resolver)
        {
            if (null != vr)
            {
                var scope = resolver.GetScope(vr);
                if (0 == string.Compare("value", vr.VariableName, StringComparison.InvariantCulture))
                {
                    // this could be a property set value reference
                    var p = scope.Member as CodeMemberProperty;
                    if (null != p)
                    {
                        var found = false;
                        for (int ic = p.SetStatements.Count, i = 0; i < ic; ++i)
                        {
                            found = false;
                            CodeDomVisitor.Visit(p.SetStatements[i], (ctx2) => {
                                if (ctx2.Target == vr)
                                {
                                    found       = true;
                                    ctx2.Cancel = true;
                                }
                            });
                            if (found)
                            {
                                break;
                            }
                        }
                        if (found)
                        {
                            CodeDomVisitor.ReplaceTarget(ctx, new CodePropertySetValueReferenceExpression());
                            return;
                        }
                    }
                }
                CodeTypeReference ctr;
                if (scope.VariableTypes.TryGetValue(vr.VariableName, out ctr))
                {
                    if (!CodeDomResolver.IsNullOrVoidType(ctr))
                    {
                        vr.UserData.Remove("slang:unresolved");
                        return;
                    }
                }
                // we need to replace it.
                if (scope.ArgumentTypes.ContainsKey(vr.VariableName))
                {
                    var a = new CodeArgumentReferenceExpression(vr.VariableName);
                    CodeDomVisitor.ReplaceTarget(ctx, a);
                    return;
                    //args.Cancel = true;
                }
                else if (scope.FieldNames.Contains(vr.VariableName))
                {
                    CodeTypeReference tref;
                    // find out where it belongs.
                    if (scope.ThisTargets.Contains(vr.VariableName))
                    {
                        var f = new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), vr.VariableName);
                        CodeDomVisitor.ReplaceTarget(ctx, f);
                        //return;
                    }
                    else if (scope.TypeTargets.TryGetValue(vr.VariableName, out tref))
                    {
                        var f = new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(tref), vr.VariableName);
                        CodeDomVisitor.ReplaceTarget(ctx, f);
                        //return;
                    }

                    return;
                }
                else if (scope.MethodNames.Contains(vr.VariableName))
                {
                    CodeTypeReference tref;
                    // find out where it belongs.
                    if (scope.ThisTargets.Contains(vr.VariableName))
                    {
                        var m = new CodeMethodReferenceExpression(new CodeThisReferenceExpression(), vr.VariableName);
                        CodeDomVisitor.ReplaceTarget(ctx, m);
                        return;
                        //args.Cancel = true;
                    }
                    if (scope.TypeTargets.TryGetValue(vr.VariableName, out tref))
                    {
                        var m = new CodeMethodReferenceExpression(new CodeTypeReferenceExpression(tref), vr.VariableName);
                        CodeDomVisitor.ReplaceTarget(ctx, m);
                        return;
                        //args.Cancel = true;
                    }
                }
                else if (scope.PropertyNames.Contains(vr.VariableName))
                {
                    CodeTypeReference tref;
                    // find out where it belongs.
                    if (scope.ThisTargets.Contains(vr.VariableName))
                    {
                        var p = new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), vr.VariableName);
                        CodeDomVisitor.ReplaceTarget(ctx, p);
                        return;
                        //args.Cancel = true;
                    }
                    else if (scope.TypeTargets.TryGetValue(vr.VariableName, out tref))
                    {
                        var p = new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(tref), vr.VariableName);
                        CodeDomVisitor.ReplaceTarget(ctx, p);
                        return;
                        //args.Cancel = true;
                    }
                }
                else if (scope.EventNames.Contains(vr.VariableName))
                {
                    CodeTypeReference tref;
                    // find out where it belongs.
                    if (scope.ThisTargets.Contains(vr.VariableName))
                    {
                        var e = new CodeEventReferenceExpression(new CodeThisReferenceExpression(), vr.VariableName);
                        CodeDomVisitor.ReplaceTarget(ctx, e);
                        return;
                        //args.Cancel = true;
                    }
                    else if (scope.TypeTargets.TryGetValue(vr.VariableName, out tref))
                    {
                        var e = new CodeEventReferenceExpression(new CodeTypeReferenceExpression(tref), vr.VariableName);
                        CodeDomVisitor.ReplaceTarget(ctx, e);
                        return;
                        //args.Cancel = true;
                    }
                }
                return;
            }
            return;
        }
        static void Demo6()
        {
            // load the xsd
            XmlSchema xsd = null;

            using (FileStream stream = new FileStream("..\\..\\Test.xsd", FileMode.Open, FileAccess.Read))
            {
                xsd = XmlSchema.Read(stream, null);
            }

            XmlSchemas xsds = new XmlSchemas();

            xsds.Add(xsd);
            xsds.Compile(null, true);
            XmlSchemaImporter xsdImporter = new XmlSchemaImporter(xsds);

            // create the codedom
            CodeNamespace   ns  = new CodeNamespace();
            CodeCompileUnit ccu = new CodeCompileUnit();

            ccu.ReferencedAssemblies.Add(typeof(XmlTypeAttribute).Assembly.GetName().ToString());
            ccu.Namespaces.Add(ns);
            XmlCodeExporter codeExporter = new XmlCodeExporter(ns, ccu);

            var maps = new List <XmlTypeMapping>();

            foreach (XmlSchemaType schemaType in xsd.SchemaTypes.Values)
            {
                maps.Add(xsdImporter.ImportSchemaType(schemaType.QualifiedName));
            }
            foreach (XmlSchemaElement schemaElement in xsd.Elements.Values)
            {
                maps.Add(xsdImporter.ImportTypeMapping(schemaElement.QualifiedName));
            }
            foreach (XmlTypeMapping map in maps)
            {
                codeExporter.ExportTypeMapping(map);
            }
            var typeMap = new Dictionary <string, CodeTypeDeclaration>(StringComparer.InvariantCulture);

            _FillTypeMap(ns, typeMap);
            foreach (var kvp in typeMap)
            {
                var td       = kvp.Value;
                var propElem = new HashSet <string>(StringComparer.InvariantCulture);
                var propAttr = new HashSet <string>(StringComparer.InvariantCulture);
                var fldMap   = new Dictionary <string, string>();
                _FillPropFldMaps(td, propElem, propAttr, fldMap);
                // fix up our xml type attribute
                foreach (CodeAttributeDeclaration d in td.CustomAttributes)
                {
                    if (0 == string.Compare(d.AttributeType.BaseType, "System.Xml.Serialization.XmlAttributeAttribute", StringComparison.InvariantCulture))
                    {
                        d.Arguments.Insert(0, new CodeAttributeArgument("TypeName", new CodePrimitiveExpression(td.Name)));
                        break;
                    }
                }
                // correct the type name
                td.Name = _ToNetCase(td.Name);
                CodeDomVisitor.Visit(td, (ctx) =>
                {
                    var fldRef = ctx.Target as CodeFieldReferenceExpression;
                    if (null != fldRef && fldMap.ContainsKey(fldRef.FieldName))
                    {
                        fldRef.FieldName = _ToPrivFldName(fldRef.FieldName);
                        return;
                    }
                    var fld = ctx.Target as CodeMemberField;
                    if (null != fld && fldMap.ContainsKey(fld.Name))
                    {
                        fld.Name = _ToPrivFldName(fld.Name);
                        var ctr  = fld.Type;
                        if (0 < ctr.ArrayRank)
                        {
                            ctr = ctr.ArrayElementType;
                        }
                        if (!CodeDomResolver.IsPrimitiveType(ctr))
                        {
                            ctr.BaseType = _ToNetCase(ctr.BaseType);
                        }
                    }
                    var prop = ctx.Target as CodeMemberProperty;
                    if (null != prop && (propElem.Contains(prop.Name) || propAttr.Contains(prop.Name)))
                    {
                        var n   = prop.Name;
                        var ctr = prop.Type;
                        if (0 < ctr.ArrayRank)
                        {
                            ctr = ctr.ArrayElementType;
                        }
                        if (!CodeDomResolver.IsPrimitiveType(ctr))
                        {
                            ctr.BaseType = _ToNetCase(ctr.BaseType);
                        }
                        prop.Name = _ToNetCase(n);
                        if (propElem.Contains(n))
                        {
                            foreach (CodeAttributeDeclaration a in prop.CustomAttributes)
                            {
                                if (0 == string.Compare("System.Xml.Serialization.XmlElementAttribute", a.AttributeType.BaseType, StringComparison.InvariantCulture))
                                {
                                    a.Arguments.Insert(0, new CodeAttributeArgument("ElementName", new CodePrimitiveExpression(n)));
                                    break;
                                }
                            }
                        }
                        else
                        {
                            foreach (CodeAttributeDeclaration a in prop.CustomAttributes)
                            {
                                if (0 == string.Compare("System.Xml.Serialization.XmlAttributeAttribute", a.AttributeType.BaseType, StringComparison.InvariantCulture))
                                {
                                    a.Arguments.Insert(0, new CodeAttributeArgument("AttributeName", new CodePrimitiveExpression(n)));
                                    break;
                                }
                            }
                        }
                    }
                });
            }

            // Check for invalid characters in identifiers
            CodeGenerator.ValidateIdentifiers(ns);

            // output the C# code
            Console.WriteLine(CodeDomUtility.ToString(ccu));
        }