SRGenerator customtool 源码修改,实现实体类生成

private CodeCompileUnit Process(string inputFileName, string FileNameSpace, ICodeGenerator generator, bool hasCustomToolNamespace, IProcessorFeedback feedback)
        {
         SortedList sList = new SortedList();
            SRGenerationOptions options = new SRGenerationOptions();
            bool generateClass = true;

            //Iterate through every resource and build up a list of resources, and get options
            using(Stream inputStream = File.OpenRead(inputFileName))
            {
                XPathDocument doc = new XPathDocument(inputStream);

                // Get options
                XPathNodeIterator headerIt = doc.CreateNavigator().Select("//resheader");  
                while(headerIt.MoveNext())
                {
                    string opt = headerIt.Current.GetAttribute("name", string.Empty);
                    XPathNodeIterator valueIt = headerIt.Current.Select("value");
                    if (valueIt.MoveNext())
                    {
                        string arg = valueIt.Current.Value;
                       
                        switch (opt.ToLower())
                        {
                            case "accessor_class_accessibility":
                                if (arg.ToLower() == "public")
                                {
                                    options.PublicSRClass = true;
                                }
                                break;

                            case "culture_info":
                                options.CultureInfoFragment = arg;
                                break;

                            case "generate_class":
                                generateClass = bool.Parse(arg);
                                break;

                            case "resource_namespace":
                                options.ResourceFileNamespace = arg;
                                break;
                        }
                    }
                }


                XPathNodeIterator it = doc.CreateNavigator().Select("//data");  
                while(it.MoveNext())
                {
                    if (it.Current.GetAttribute("type", String.Empty).Length != 0)
                    {
                        continue; // Only interested in string resources
                    }

                    string key = it.Current.GetAttribute("name", String.Empty);
                    string textValue = null;
                    string commentValue = null;

                    // Get the value and comment elements
                    XPathNodeIterator valueIt = it.Current.SelectChildren(XPathNodeType.Element);
                    while (valueIt.MoveNext())
                    {
                        if (valueIt.Current.Name == "value")
                        {
                            textValue = valueIt.Current.Value;
                        }
                        else if (valueIt.Current.Name == "comment")
                        {
                            commentValue = valueIt.Current.Value;
                        }
                    }

                    sList.Add(key, new ResourceHolder(key, textValue, commentValue) );
                }
            }

            string className = Path.GetFileNameWithoutExtension(inputFileName);           
           
            CodeCompileUnit compileUnit = new CodeCompileUnit();

            //Just for VB.NET
            compileUnit.UserData.Add("AllowLateBound", false);
            compileUnit.UserData.Add("RequireVariableDeclaration", true);

            //Dummy namespace, so the Import statements would appear above the main namespace declaration
            CodeNamespace dummyNamespace = new CodeNamespace("");
            compileUnit.Namespaces.Add(dummyNamespace);


            if (hasCustomToolNamespace
                && options.ResourceFileNamespace == null)
            {
                string errorMessage = "You must specify the option resource_namespace when using a Custom Tool Namespace, to provide the namespace used for the resources.";
                //dummyNamespace.Comments.Add(new CodeCommentStatement(errorMessage));
                //feedback.LineError(errorMessage, null, 0);
                return new CodeSnippetCompileUnit("#error " + errorMessage);
            }

            if (!generateClass)
            {
                dummyNamespace.Comments.Add(new CodeCommentStatement("-----------------------------------------------------------------------------"));
                dummyNamespace.Comments.Add(new CodeCommentStatement(" <autogeneratedinfo>"));
                dummyNamespace.Comments.Add(new CodeCommentStatement("     This code was generated by:"));
                dummyNamespace.Comments.Add(new CodeCommentStatement("       SR Resource Generator custom tool for VS.NET, by Martin Granell, Readify"));
                dummyNamespace.Comments.Add(new CodeCommentStatement(""));
                dummyNamespace.Comments.Add(new CodeCommentStatement("     NO CLASS WILL BE GENERATED "));
                dummyNamespace.Comments.Add(new CodeCommentStatement("     as the resource file contains the option: "));
                dummyNamespace.Comments.Add(new CodeCommentStatement("          generate_class = false. "));
                dummyNamespace.Comments.Add(new CodeCommentStatement(""));
                dummyNamespace.Comments.Add(new CodeCommentStatement("     The resource filename is:" + inputFileName));
                dummyNamespace.Comments.Add(new CodeCommentStatement(""));
                dummyNamespace.Comments.Add(new CodeCommentStatement("     Generated: " + DateTime.Now.ToString("f", new CultureInfo("en-US"))));
                dummyNamespace.Comments.Add(new CodeCommentStatement(" </autogeneratedinfo>"));
                dummyNamespace.Comments.Add(new CodeCommentStatement("-----------------------------------------------------------------------------"));                               
                return compileUnit;
            }

            //Namespace Import
            dummyNamespace.Imports.Add(new CodeNamespaceImport("System"));
            dummyNamespace.Imports.Add(new CodeNamespaceImport("System.Resources"));
            dummyNamespace.Imports.Add(new CodeNamespaceImport("System.Reflection"));

            //Namespace
            CodeNamespace nSpace = new CodeNamespace(FileNameSpace);
            compileUnit.Namespaces.Add(nSpace);

           

            //Namespace comments
   #region [liubin 2006-05-16 17:42] 增加修改记录注释
            nSpace.Comments.Add(new CodeCommentStatement("-----------------------------------------------------------------------------"));
            nSpace.Comments.Add(new CodeCommentStatement(" <autogeneratedinfo>"));
            nSpace.Comments.Add(new CodeCommentStatement("     This code was generated by:"));
            nSpace.Comments.Add(new CodeCommentStatement("       SR Resource Generator custom tool for VS.NET, by Martin Granell, Readify"));
            nSpace.Comments.Add(new CodeCommentStatement(""));
            nSpace.Comments.Add(new CodeCommentStatement("     It contains classes defined from the contents of the resource file:"));
            nSpace.Comments.Add(new CodeCommentStatement("       " + inputFileName));
            nSpace.Comments.Add(new CodeCommentStatement(""));
            nSpace.Comments.Add(new CodeCommentStatement("     Generated: " + DateTime.Now.ToString("f", new CultureInfo("en-US"))));
   nSpace.Comments.Add(new CodeCommentStatement("     Modified by:  liubin 2006-05-16 17:42"));
   nSpace.Comments.Add(new CodeCommentStatement("     修改记录:"));
   nSpace.Comments.Add(new CodeCommentStatement("             1.原所有构建static方法改写成构建Final方法;"));
   nSpace.Comments.Add(new CodeCommentStatement("             2.原所有常量字段属性被剔除;"));
   nSpace.Comments.Add(new CodeCommentStatement("             3.在SR Class中增加静态字段mENSR、mCNSR和非静态字段mKeys;"));
   nSpace.Comments.Add(new CodeCommentStatement("             4.在SR Class中增加静态方法GetENSR和GetCNSR"));
   nSpace.Comments.Add(new CodeCommentStatement("             5.在SR Class中增加构造函数SR"));
            nSpace.Comments.Add(new CodeCommentStatement(" </autogeneratedinfo>"));
            nSpace.Comments.Add(new CodeCommentStatement("-----------------------------------------------------------------------------"));
   #endregion

            // Define SR class
            CodeTypeDeclaration cSR = new CodeTypeDeclaration(className);

            // CodeDom Sucks. It doesn't allow support for specifying assembly visibility.
            // So we have to do a search and replace on the resulting text after we have generated
            // the file.
            cSR.TypeAttributes = TypeAttributes.Public;
            _convertPublicToInternal = !options.PublicSRClass;

   #region [liubin 2005-06-16] 增加SR私有实体类字段
   CodeConstructor cmSRCodeConstructor = new CodeConstructor();
   cmSRCodeConstructor.Attributes  = MemberAttributes.Private;
   cmSRCodeConstructor.Name   = "SR";
   CodeObjectCreateExpression coCreateExp = new CodeObjectCreateExpression();
   coCreateExp.CreateType = new CodeTypeReference("Keys");
   cmSRCodeConstructor.Statements.Add(new CodeAssignStatement(
    new CodeFieldReferenceExpression(
    new CodeThisReferenceExpression(),"mKeys"),
    coCreateExp));
   cSR.Members.Add(cmSRCodeConstructor);
   #endregion

   #region [liubin 2005-06-16] 增加SR私有实体类字段
   CodeMemberField cmCNSRClassField = new CodeMemberField();
   cmCNSRClassField.Name    = "mCNSR";
   cmCNSRClassField.Attributes  = MemberAttributes.Private | MemberAttributes.Static;
   cmCNSRClassField.Type    = new CodeTypeReference(className);
   cSR.Members.Add(cmCNSRClassField);

   CodeMemberField cmENSRClassField = new CodeMemberField();
   cmENSRClassField.Name    = "mENSR";
   cmENSRClassField.Attributes      = MemberAttributes.Private | MemberAttributes.Static;
   cmENSRClassField.Type    = new CodeTypeReference(className);
   cSR.Members.Add(cmENSRClassField);
   #endregion

   #region  [liubin 2005-06-16] 增加SR公共静态实体类方法
   CodeMemberMethod mGetENSRInstance = new CodeMemberMethod();
   mGetENSRInstance.Attributes  = MemberAttributes.Public | MemberAttributes.Static;
   mGetENSRInstance.ReturnType  = new CodeTypeReference(className);
   mGetENSRInstance.Name        = "GetENSR";

   mGetENSRInstance.Comments.Add(new CodeCommentStatement("获得英文SR"));
   CodeObjectCreateExpression coCreaterENSRExp = new CodeObjectCreateExpression();
   coCreaterENSRExp.CreateType = new CodeTypeReference(className);

//   CodeExpression enExpression = new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(
//    new CodeTypeReference("LanguageCulture")),"GetCultureInfo",
//    new CodePrimitiveExpression("en-US"));
   CodeObjectCreateExpression enObjectExpression = new CodeObjectCreateExpression();
   enObjectExpression.CreateType = new CodeTypeReference(typeof(CultureInfo));
   enObjectExpression.Parameters.Add(new CodePrimitiveExpression("en-US"));

   mGetENSRInstance.Statements.Add(new CodeConditionStatement(
    new CodeSnippetExpression("mENSR == null"),
    new CodeAssignStatement(new CodeFieldReferenceExpression(null, "mENSR"),
    coCreaterENSRExp)));

   mGetENSRInstance.Statements.Add(
    new CodeAssignStatement(
    new CodePropertyReferenceExpression(null, "mENSR.Culture"),enObjectExpression));

   mGetENSRInstance.Statements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(null,"mENSR")));
   cSR.Members.Add(mGetENSRInstance);
   #endregion

   #region [liubin 2005-06-16] 增加SR公共静态实体类方法
   CodeMemberMethod mGetCNSRInstance = new CodeMemberMethod();
   mGetCNSRInstance.Attributes  = MemberAttributes.Public | MemberAttributes.Static;
   mGetCNSRInstance.ReturnType  = new CodeTypeReference(className);
   mGetCNSRInstance.Name        = "GetCNSR";
   mGetCNSRInstance.Comments.Add(new CodeCommentStatement("获得中文SR"));

   CodeObjectCreateExpression coCreaterCNSRExp = new CodeObjectCreateExpression();
   coCreaterCNSRExp.CreateType = new CodeTypeReference(className);

   mGetCNSRInstance.Statements.Add(new CodeConditionStatement(
    new CodeSnippetExpression("mCNSR == null"),
    new CodeAssignStatement(new CodeFieldReferenceExpression(null, "mCNSR"),
    coCreaterCNSRExp)));
//   
//   CodeExpression cnExpression = new CodeMethodInvokeExpression(
//    new CodeTypeReferenceExpression(
//    new CodeTypeReference("LanguageCulture")),"GetCultureInfo",
//    new CodePrimitiveExpression("zh-CN"));

   CodeObjectCreateExpression cnObjectExpression = new CodeObjectCreateExpression();
   cnObjectExpression.CreateType = new CodeTypeReference(typeof(CultureInfo));
   cnObjectExpression.Parameters.Add(new CodePrimitiveExpression("zh-CN"));
  
   mGetCNSRInstance.Statements.Add(
    new CodeAssignStatement(
    new CodePropertyReferenceExpression(null, "mCNSR.Culture"),cnObjectExpression));

   /*
    mGetSRInstance.Statements.Add(
    new CodeConditionStatement(
    new CodeBinaryOperatorExpression(
    new CodeArgumentReferenceExpression("mLanguage"), CodeBinaryOperatorType.ValueEquality,
    new  CodeSnippetExpression("LanguageOption.CN")),
    new CodeStatement[]{
            new CodeAssignStatement(new CodePropertyReferenceExpression(null, "mSR.Culture"),
            ceRight1)},
    new CodeStatement[]{
            new CodeAssignStatement(new CodePropertyReferenceExpression(null,"mSR.Culture"),
            ceRight2)}));
            */
   mGetCNSRInstance.Statements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(null,"mCNSR")));
   cSR.Members.Add(mGetCNSRInstance);
   #endregion

 

            if (options.CultureInfoFragment == null)
            {
                // Create Static Culture property
                CodeMemberProperty cmStaticCulture = new CodeMemberProperty();
                cmStaticCulture.Name = "Culture";
    // [liubin 2006-05-16 13:45] 不生成静态属性
//                cmStaticCulture.Attributes = MemberAttributes.Public | MemberAttributes.Static;
    cmStaticCulture.Attributes = MemberAttributes.Public | MemberAttributes.Final;
                cmStaticCulture.Type = new CodeTypeReference(typeof(CultureInfo));
                cmStaticCulture.GetStatements.Add(
                    new CodeMethodReturnStatement(
                    new CodePropertyReferenceExpression(
                    new CodeTypeReferenceExpression("mKeys"), "Culture")));
                cmStaticCulture.SetStatements.Add(
                    new CodeAssignStatement(
                    new CodePropertyReferenceExpression(
                    new CodeTypeReferenceExpression("mKeys"), "Culture"), new CodeArgumentReferenceExpression("value")));
               
                cSR.Members.Add(cmStaticCulture);
            }

            // Define Keys class
            CodeTypeDeclaration cKeys = new CodeTypeDeclaration("Keys");

            cKeys.TypeAttributes = TypeAttributes.Public;

            // Create resource manager
            //   static ResourceManager resourceManager =
            //            new ResourceManager("Microsoft.Practices.EnterpriseLibrary.Data.SR", typeof(Microsoft.Practices.EnterpriseLibrary.Data.SR).Module.Assembly );
            //
            CodeMemberField fResourceManager = new CodeMemberField(typeof(ResourceManager), "resourceManager");
           
   #region [liubin 2005-06-16] 增加mKeys私有实体类字段
   CodeMemberField cmKeyClassField  = new CodeMemberField();
   cmKeyClassField.Name    = "mKeys";
   cmKeyClassField.Attributes   = MemberAttributes.Private;
   cmKeyClassField.Type    = new CodeTypeReference("Keys");
   cSR.Members.Add(cmKeyClassField);
   #endregion

   // [liubin 2006-05-16 13:52] 不用静态属性
//            fResourceManager.Attributes = MemberAttributes.Static;
   fResourceManager.Attributes = MemberAttributes.Private;

            if (options.ResourceFileNamespace != null)
            {
                string resName = className;
                if (options.ResourceFileNamespace.Length > 0)
                {
                    resName = options.ResourceFileNamespace.Length  + "." + resName;
                }
                fResourceManager.InitExpression = new CodeObjectCreateExpression(typeof(ResourceManager), new CodePrimitiveExpression(options.ResourceFileNamespace + "." + className), new CodePropertyReferenceExpression(new CodeTypeOfExpression(className), "Assembly"));
            }
            else
            {
                fResourceManager.InitExpression = new CodeObjectCreateExpression(typeof(ResourceManager), new CodeTypeOfExpression(className));
            }
            cKeys.Members.Add(fResourceManager);

            CodeExpression cultureCodeExp;
            if (options.CultureInfoFragment == null) // Add a property that is settable
            {
                // Culture field and property
                CodeMemberField fCulture = new CodeMemberField(typeof(CultureInfo), "_culture");
    // [liubin 2006-05-16 13:52] 不用静态属性
//                fCulture.Attributes = MemberAttributes.Static;
    fCulture.Attributes = MemberAttributes.Private | MemberAttributes.Final;
                fCulture.InitExpression = new CodePrimitiveExpression(null);
                cKeys.Members.Add(fCulture);

                CodeMemberProperty pCulture = new CodeMemberProperty();
    // [liubin 2006-05-16 13:52] 不用静态属性
//                pCulture.Attributes = MemberAttributes.Static | MemberAttributes.Public;
    pCulture.Attributes = MemberAttributes.Public | MemberAttributes.Final;
                pCulture.Type = new CodeTypeReference( typeof(CultureInfo));
                pCulture.Name = "Culture";
                pCulture.GetStatements.Add( new CodeMethodReturnStatement( new CodeFieldReferenceExpression(null, "_culture") ));
                pCulture.SetStatements.Add( new CodeAssignStatement( new CodeFieldReferenceExpression(null, "_culture"), new CodeArgumentReferenceExpression("value")));
                cKeys.Members.Add(pCulture);

                cultureCodeExp = new CodeFieldReferenceExpression(null, "_culture");
            }
            else
            {
                cultureCodeExp = new CodeSnippetExpression(options.CultureInfoFragment);
            }

            // Get String methods

            // No parameters, just return the result of the resourceManager.GetString method.
            //  return resourceManager.GetString( key, _culture );
            CodeMemberMethod mGetStringNoParams = new CodeMemberMethod();
            mGetStringNoParams.Name = "GetString";
   // [liubin 2006-05-16 13:52] 不用静态属性
//            mGetStringNoParams.Attributes = MemberAttributes.Public | MemberAttributes.Static;
   mGetStringNoParams.Attributes = MemberAttributes.Public|MemberAttributes.Final;
            mGetStringNoParams.ReturnType = new CodeTypeReference(typeof(string));
            mGetStringNoParams.Parameters.Add( new CodeParameterDeclarationExpression(typeof(string), "key") );
            mGetStringNoParams.Statements.Add( new CodeMethodReturnStatement(
                new CodeMethodInvokeExpression(
                new CodeFieldReferenceExpression(null, "resourceManager"),
                "GetString",
                new CodeArgumentReferenceExpression("key"),
                cultureCodeExp)));
            cKeys.Members.Add(mGetStringNoParams);

            // With parameters, format the results using String.Format
            // return msg;
            CodeMemberMethod mGetStringWithParams = new CodeMemberMethod();
            mGetStringWithParams.Name = "GetString";
   // [liubin 2006-05-16 13:52] 不用静态属性
//            mGetStringWithParams.Attributes = MemberAttributes.Public | MemberAttributes.Static;
   mGetStringWithParams.Attributes = MemberAttributes.Public|MemberAttributes.Final;
            mGetStringWithParams.ReturnType = new CodeTypeReference(typeof(string));
            mGetStringWithParams.Parameters.Add(
                new CodeParameterDeclarationExpression(typeof(string), "key"));
            mGetStringWithParams.Parameters.Add(
                new CodeParameterDeclarationExpression(typeof(object[]), "args"));

            // string msg = resourceManager.GetString( key, _culture );
            mGetStringWithParams.Statements.Add(
                new CodeVariableDeclarationStatement(typeof(string), "msg",
                new CodeMethodInvokeExpression(
                new CodeFieldReferenceExpression(null, "resourceManager"),
                "GetString",
                new CodeArgumentReferenceExpression("key"),
                cultureCodeExp)));

            // msg = string.Format( msg, args );
            mGetStringWithParams.Statements.Add(
                new CodeAssignStatement( new CodeVariableReferenceExpression("msg"),
                new CodeMethodInvokeExpression( new CodeTypeReferenceExpression(typeof(string)), "Format", new CodeVariableReferenceExpression("msg"), new CodeArgumentReferenceExpression("args"))));

            // return msg
            mGetStringWithParams.Statements.Add(
                new CodeMethodReturnStatement(new CodeVariableReferenceExpression("msg")));

            cKeys.Members.Add(mGetStringWithParams);

            IDictionaryEnumerator resEnumerator = sList.GetEnumerator();

         Regex safeRegex = new Regex("[^a-zA-Z0-9_]");

            // Create a class definition for each string entry 
            while(resEnumerator.MoveNext())
            {
                ResourceHolder resource = (ResourceHolder)resEnumerator.Value;

                // Create a safe identifier
                string safeKey = XmlConvert.EncodeName(resource.Key);

                // Deal with an initial numeral.
                if (safeKey[0] >= '0' && safeKey[0] <= '9')
                    safeKey = "_" + safeKey;
               
                // Make sure we don't conflict with a language identifier.
                safeKey = generator.CreateValidIdentifier(safeKey);

                // The VS Generator always lower cases the first letter, which is not
                // wanted in this case.
                safeKey = char.ToUpper(safeKey[0], CultureInfo.InvariantCulture) + safeKey.Substring(1);

                /*
                //It is necessary to know how many replaceable parameters the string has
                string ParameterMatchExpression = @"(\{[^\}\{]+\})";
                MatchCollection mc = Regex.Matches(resource.Text, ParameterMatchExpression);
                //Don't include duplicates in count as String.Format argument can be specified
                //more than once, ie: "First: {0}, Second: {1}, First again: {0}"
                StringCollection parameters = new StringCollection();
                foreach(Match match in mc)
                {
                    if(!parameters.Contains(match.Value))
                    {
                        parameters.Add(match.Value);
                    }
                }
                */


                // Get parameter names from comma sep names in comment
                string[] parameterNames = new string[0];
                if (resource.Comment != null)
                {
                    parameterNames = resource.Comment.Split(',');
                }

                   
                if (parameterNames.Length > 0)
                {
                    // Create as a method that takes the right number of parameters.

                       
                    CodeMemberMethod mGetString = new CodeMemberMethod();
                    mGetString.Name = safeKey;
     // [liubin 2006-05-16 13:52] 不用静态属性
     mGetString.Attributes =  MemberAttributes.Public|MemberAttributes.Final;
//                    mGetString.Attributes = MemberAttributes.Static | MemberAttributes.Public;
                    mGetString.ReturnType= new CodeTypeReference(typeof(string));

                    //Create the argument lists
                    CodeExpression[] args = new CodeExpression[parameterNames.Length];

                    for(int i = 0; i < parameterNames.Length; i++)
                    {
                        string parameterName = parameterNames[i];
                        parameterName = parameterName.Trim();
                        if (parameterName.IndexOf(' ') > -1)
                        {
                            // parameter name includes type.
                            string typeName = MapType(parameterName.Substring(0,parameterName.IndexOf(' ')).Trim());
                            parameterName = parameterName.Substring(parameterName.IndexOf(' ')+1).Trim();

                            mGetString.Parameters.Add(new CodeParameterDeclarationExpression(typeName, parameterName));
                        }
                        else
                        {
                            mGetString.Parameters.Add(new CodeParameterDeclarationExpression(typeof(object), parameterName));
                        }
                        args[i] = new CodeArgumentReferenceExpression(parameterName);
                    }
                       
                    mGetString.Statements.Add(
                        new CodeMethodReturnStatement(
                        new CodeMethodInvokeExpression(
                        new CodeTypeReferenceExpression("mKeys"),
                        "GetString",
                        new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("mKeys"), safeKey),
                        new CodeArrayCreateExpression(typeof(object), args))));

                    cSR.Members.Add(mGetString);
                }
                else
                {
                    // Create as a property
                    CodeMemberProperty pGetString = new CodeMemberProperty();
                    pGetString.Name = safeKey;
     // [liubin 2006-05-16 13:52] 不用静态属性
//                    pGetString.Attributes = MemberAttributes.Static | MemberAttributes.Public;
     pGetString.Attributes = MemberAttributes.Public|MemberAttributes.Final;
                    pGetString.Type= new CodeTypeReference(typeof(string));

                    pGetString.GetStatements.Add(
                        new CodeMethodReturnStatement(
                        new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("mKeys"), "GetString", new CodeFieldReferenceExpression(new CodeTypeReferenceExpression("mKeys"), safeKey))));

                    cSR.Members.Add(pGetString);
                }

                // Add a const field to the Keys class that contains the actual reference
                CodeMemberField fKey = new CodeMemberField(typeof(string), safeKey);
                fKey.InitExpression = new CodePrimitiveExpression(resource.Key);
    // [liubin 2006-05-16 13:52] 不用静态属性
//                fKey.Attributes = MemberAttributes.Const | MemberAttributes.Public;
    fKey.Attributes = MemberAttributes.Public;
                cKeys.Members.Add(fKey);


            }
            cSR.Members.Add(cKeys);
            nSpace.Types.Add(cSR);

            return compileUnit;
        }

你可能感兴趣的:(generator)