C# 开发学习笔记:动态生成.cs文件

学习自:https://blog.csdn.net/csdn1987/article/details/89677563

using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace PXPublic
{
    /// <summary>
    /// 动态生成类文件
    /// </summary>
    public class GeneratorClass
    {
        static string fieldName = "";
        static string commentText = "";//生成字段、属性、方法时的注释文本
        static string methodCode = "";//生成方法时方法内部的代码片段

        /// <summary>
        /// 动态生成表结构类文件
        /// </summary>
        /// <param name="tableInfo">要生成类文件的表信息</param>
        public static void GeneratorTableClass(MyDataSet tableInfo)
        {
            for (int i = 0; i < tableInfo.Tables[0].Rows.Count; i++)
            {
                //准备一个代码编译器单元

                CodeCompileUnit unit = new CodeCompileUnit();
                //设置命名空间(这个是指要生成的类的空间)
                CodeNamespace myNamespace = new CodeNamespace("TableManager");

                //导入必要的命名空间引用
                myNamespace.Imports.Add(new CodeNamespaceImport("System"));
                myNamespace.Imports.Add(new CodeNamespaceImport("System.Collections.Generic"));
                myNamespace.Imports.Add(new CodeNamespaceImport("System.Linq"));
                myNamespace.Imports.Add(new CodeNamespaceImport("System.Text"));
                myNamespace.Imports.Add(new CodeNamespaceImport("System.Threading.Tasks"));
                myNamespace.Imports.Add(new CodeNamespaceImport("System.Data"));

                //声明一个名为className的CodeTypeDeclaration 
                CodeTypeDeclaration myClass = new CodeTypeDeclaration(tableInfo.Tables[0].Rows[i]["tableName"].ToString()); 
                myClass.IsClass = true;    //指定该CodeTypeDeclaration为一个类
                myClass.TypeAttributes = TypeAttributes.Public;  //该类为公开的

                //把这个类放在这个命名空间下
                myNamespace.Types.Add(myClass);

                //把该命名空间加入到编译器单元的命名空间集合中
                unit.Namespaces.Add(myNamespace);

                // 根据表名查询表的字段信息
                string sql = " SELECT  DISTINCT A.COLUMN_NAME" +
                            "     ,B.COMMENTS " +
                            "     ,A.DATA_TYPE " +
                            "     ,A.DATA_LENGTH" +
                            "     ,A.DATA_SCALE    " +
                            "     ,A.NULLABLE    " +
                            "     ,D.col#    " +
                            "     FROM USER_TAB_COLUMNS A,USER_COL_COMMENTS B,sys.col$ D" +
                            "     WHERE A.TABLE_NAME = B.TABLE_NAME" +
                            "     AND A.COLUMN_NAME = B.COLUMN_NAME" +
                            "     AND D.NAME= A.COLUMN_NAME" +
                            "     AND D.obj# IN (SELECT object_id FROM all_objects WHERE  object_name = @TABLE_NAME )" +
                            "     AND A.TABLE_NAME =@TABLE_NAME " +
                            "     ORDER BY D.col# ";
                DBManager.ParameterAdd("TABLE_NAME", tableInfo.Tables[0].Rows[i]["tableName"].ToString());
                MyDataSet outDs = new MyDataSet();
                int resultFlag = PXPublic.DBManager.ExcuteSelect(sql, outDs);
                // 抽时间添加log4Net日志模块
                
                //公用字段声明
                CodeMemberField member = new CodeMemberField(typeof(System.String), "tableName");
                member.Attributes = MemberAttributes.Private | MemberAttributes.Static; //设置访问类型
                commentText = "\n/ <summary>\n" +
                                    "/ 数据表名称\n" +
                                    "/ </summary>";
                member.Comments.Add(new CodeCommentStatement(commentText));
                myClass.Members.Add(member);  //把该字段添加到类中

                member = new CodeMemberField(typeof(System.String), "tableCname");
                member.Attributes = MemberAttributes.Private | MemberAttributes.Static; //设置访问类型
                commentText = "\n/ <summary>\n" +
                                    "/ 数据表描述\n" +
                                    "/ </summary>";
                member.Comments.Add(new CodeCommentStatement(commentText));
                myClass.Members.Add(member);  //把该字段添加到类中

                //添加属性
                CodeMemberProperty property = new CodeMemberProperty();               

                // 声明数据表结构字段
                foreach (DataRow dr in outDs.Tables[0].Rows)
                {
                    // 字段相关属性设置
                    fieldName = dr["COLUMN_NAME"].ToString().ToLower()+"_";
                    if (dr["DATA_TYPE"].ToString() == "VARCHAR2")
                        member = new CodeMemberField(typeof(System.String), fieldName);
                    else if (dr["DATA_TYPE"].ToString() == "NUMBER")
                        member = new CodeMemberField(typeof(System.Decimal), fieldName);
                    member.Attributes = MemberAttributes.Private | MemberAttributes.Static; //设置访问类型
                    commentText = "\n/ <summary>\n" +
                                        "/ " + dr["COMMENTS"].ToString() +"\n"+
                                        "/ </summary>";
                    member.Comments.Add(new CodeCommentStatement(commentText));
                    myClass.Members.Add(member);  //把该字段添加到类中


                    // 属性相关信息设置
                    property = new CodeMemberProperty();
                    //设置访问类型
                    property.Attributes = MemberAttributes.Public | MemberAttributes.Static;
                    //对象名称
                    property.Name = dr["COLUMN_NAME"].ToString();
                    //有get
                    property.HasGet = true;
                    //有set
                    property.HasSet = true;
                    //设置property的类型
                    if (dr["DATA_TYPE"].ToString() == "VARCHAR2")
                        property.Type = new CodeTypeReference(typeof(System.String));
                    else if (dr["DATA_TYPE"].ToString() == "NUMBER")
                        property.Type = new CodeTypeReference(typeof(System.Decimal));                    
                    //添加注释
                    property.Comments.Add(new CodeCommentStatement(commentText));
                    //设置get里面的代码:get { return REC_CREATOR_;};由于属性使用静态属性,因此在设置get代码时变量不能使用this
                    property.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(null, fieldName)));
                    //property.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), dr["COLUMN_NAME"].ToString().ToLower())));
                    //设置set里面的代码:set { REC_CREATOR_ = value; };由于属性使用静态属性,因此在设置set代码时变量不能使用this
                    property.SetStatements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(null, fieldName), new CodePropertySetValueReferenceExpression()));
                    ///添加到Customerclass类中
                    myClass.Members.Add(property);
                }
                //添加MergeFrom方法
                CodeMemberMethod method = new CodeMemberMethod();
                //方法名
                method.Name = "MergeFrom";
                //访问类型
                method.Attributes = MemberAttributes.Public | MemberAttributes.Static;
                //添加一个参数
                method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(DataRow), "dataRow"));
                commentText = "\n/ <summary>\n" +
                                        "/ 从数据表中将对应字段名的值复制到当前类的同名属性中\n" +
                                        "/ <param name=\"dataRow\">要复制数据数据行</param>\n" +
                                        "/ </summary>";
                method.Comments.Add(new CodeCommentStatement(commentText));
                //设置返回值类型:int/不设置则为void
                //method.ReturnType = new CodeTypeReference(typeof(int));
                method.ReturnType = new CodeTypeReference();
                //设置返回值(使用指定的代码片段初始化方法)
                method.Statements.Add(new CodeSnippetStatement("  "));
                ///将方法添加到myClass类中
                myClass.Members.Add(method);

                //添加Query方法
                method = new CodeMemberMethod();
                //方法名
                method.Name = "Query";
                commentText = "\n/ <summary>\n" +
                                        "/ 使用指定字段查询数据,查询结果必须唯一\n" +
                                        "/ <param name=\"conditionColumn\">查询条件列</param>\n" +
                                        "/ </summary>";
                method.Comments.Add(new CodeCommentStatement(commentText));
                //访问类型
                method.Attributes = MemberAttributes.Public | MemberAttributes.Static;
                //添加一个参数
                method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "conditionColumn"));
                //设置返回值类型:int/不设置则为void
                //method.ReturnType = new CodeTypeReference(typeof(int));
                method.ReturnType = new CodeTypeReference();
                //设置返回值
                methodCode ="              if (ConditionColumn.Trim() == \"\")\n"+
                            "                return;\n"+
                            "            PXPublic.MyDataSet outDs = new PXPublic.MyDataSet();\n"+
                            "            string sql = \" SELECT * FROM \"+tableName+\" WHERE 1=1  \";\n"+
                            "            if (ConditionColumn.Trim().Contains(\",\"))\n"+
                            "            {\n"+
                            "                string[] ConditionColumn_temp = ConditionColumn.Split(',');\n"+
                            "                foreach (string column in ConditionColumn_temp)\n"+
                            "                {\n"+
                            "                    // 获取当前类中的所有属性\n"+
                            "                    Type t = this.GetType();\n"+
                            "                    PropertyInfo[] info = t.GetProperties();\n"+
                            "                    // 判断当前传入的条件列是否属于当前类的属性(相当于判断当前传入列是否属于数据表字段)\n"+
                            "                    // 属于则获取到当前属性的值\n"+
                            "                    foreach (PropertyInfo preperty in info)\n"+
                            "                    {\n"+
                            "                        if (column == preperty.Name)\n"+
                            "                        {\n"+
                            "                            sql += string.Format(\" AND \"+column+\" = @\"+column);\n"+
                            "                            object temp = preperty.GetValue(this, null);\n"+
                            "                            PXPublic.DBManager.ParameterAdd(column, preperty.GetValue(this,null));\n"+
                            "                        }\n"+
                            "                    }\n"+
                            "                }\n"+
                            "            }\n"+
                            "            PXPublic.DBManager.ExcuteSelect((sql), outDs);\n"+
                            "            if(outDs.Tables[0].Rows.Count==1)\n"+
                            "            {\n"+
                            "            }\n"+
                            "            else\n"+
                            "            {\n"+
                            "                PXPublic.SysMesgInfo.returnMsg = \"当前查询结果不唯一\";\n"+
                            "            } ";
                method.Statements.Add(new CodeSnippetStatement(methodCode));
                ///将方法添加到myClass类中
                myClass.Members.Add(method);

                //添加QueryCount方法
                method = new CodeMemberMethod();
                //方法名
                method.Name = "QueryCount";
                commentText = "\n/ <summary>\n" +
                                       "/ 使用指定字段查询数据记录条数\n" +
                                       "/ <param name=\"conditionColumn\">查询条件列</param>\n" +
                                       "/ </summary>";
                method.Comments.Add(new CodeCommentStatement(commentText));
                //访问类型
                method.Attributes = MemberAttributes.Public | MemberAttributes.Static;
                //添加一个参数
                method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "conditionColumn"));
                //设置返回值类型:int/不设置则为void
                method.ReturnType = new CodeTypeReference(typeof(int));
                //method.ReturnType = new CodeTypeReference();
                //设置返回值
                methodCode = "            if (ConditionColumn.Trim() == \"\")\n" +
                                    "                return 0;\n" +
                                    "            PXPublic.MyDataSet outDs = new PXPublic.MyDataSet();\n" +
                                    "            string sql = \" SELECT COUNT(*) FROM \" + tableName + \" WHERE 1=1  \";\n" +
                                    "            if (ConditionColumn.Trim().Contains(\",\"))\n" +
                                    "            {\n" +
                                    "               string[] ConditionColumn_temp = ConditionColumn.Split(',');\n" +
                                    "               foreach (string column in ConditionColumn_temp)\n" +
                                    "               {\n" +
                                    "                   // 获取当前类中的所有属性\n" +
                                    "                   Type t = this.GetType();\n" +
                                    "                   PropertyInfo[] info = t.GetProperties();\n" +
                                    "                   // 判断当前传入的条件列是否属于当前类的属性(相当于判断当前传入列是否属于数据表字段)\n" +
                                    "                   // 属于则获取到当前属性的值\n" +
                                    "                   foreach (PropertyInfo preperty in info)\n" +
                                    "                   {\n" +
                                    "                       if (column == preperty.Name)\n" +
                                    "                       {\n" +
                                    "                           sql += string.Format(\" AND \" + column + \" = @\" + column);\n" +
                                    "                           object temp = preperty.GetValue(this, null);\n" +
                                    "                           PXPublic.DBManager.ParameterAdd(column, preperty.GetValue(this, null));\n" +
                                    "                       }\n" +
                                    "                   }\n" +
                                    "               }\n" +
                                    "            }\n" +
                                    "            PXPublic.DBManager.ExcuteSelect((sql), outDs);\n" +
                                    "            return outDs.Tables[0].Rows.Count; ";
                method.Statements.Add(new CodeSnippetStatement(methodCode));
                ///将方法添加到myClass类中
                myClass.Members.Add(method);


                //添加Insert方法
                method = new CodeMemberMethod();
                //方法名
                method.Name = "Insert";
                commentText = "\n/ <summary>\n" +
                                       "/ 新增一条数据到数据库对应数据表中\n" +
                                       "/ </summary>";
                method.Comments.Add(new CodeCommentStatement(commentText));
                //访问类型
                method.Attributes = MemberAttributes.Public | MemberAttributes.Static;
                //添加一个参数
                //method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "conditionColumn"));
                //设置返回值类型:int/不设置则为void
                //method.ReturnType = new CodeTypeReference(typeof(int));
                method.ReturnType = new CodeTypeReference();
                //设置返回值
                methodCode =    "              PXPublic.MyDataSet outDs = new PXPublic.MyDataSet();\n"+
                                "            string InsertCol = \" \";\n"+
                                "            string InsertSelect = \"  \";\n"+
                                "            int prepertyIndex = 0;\n"+
                                "            // 获取当前类中的所有属性\n"+
                                "            Type t = this.GetType();\n"+
                                "            PropertyInfo[] info = t.GetProperties();\n"+
                                "            // 判断当前传入的条件列是否属于当前类的属性(相当于判断当前传入列是否属于数据表字段)\n"+
                                "            // 属于则获取到当前属性的值\n"+
                                "            foreach (PropertyInfo preperty in info)\n"+
                                "            {\n"+
                                "                InsertCol += preperty.Name;\n"+
                                "                if (preperty.GetValue(this, null).GetType() == typeof(String))\n"+
                                "                    InsertSelect += \"'\" + preperty.GetValue(this, null) + \"'\";\n"+
                                "                else if (preperty.GetValue(this, null).GetType() == typeof(Decimal))\n"+
                                "                    InsertSelect += preperty.GetValue(this, null);\n"+
                                "                if(prepertyIndex!=info.GetLength(0))\n"+
                                "                {\n"+
                                "                    InsertSelect += \",\";\n"+
                                "                    InsertCol += \",\";\n"+
                                "                }\n"+
                                "            }\n"+
                                "            string sql = \" INSERT INTO \" + tableName + \" ( \" + InsertCol + \") VALUES ( \" + InsertSelect + \" )\";\n"+
                                "            PXPublic.DBManager.ExcuteSelect(sql, outDs);\n"+
                                "            if (outDs.Tables[0].Rows.Count == 1)\n"+
                                "            {\n"+
                                "            }\n"+
                                "            else\n"+
                                "            {\n"+
                                "                PXPublic.SysMesgInfo.returnMsg = \"当前查询结果不唯一\";\n"+
                                "            } ";
                method.Statements.Add(new CodeSnippetStatement(methodCode));
                ///将方法添加到myClass类中
                myClass.Members.Add(method);


                //添加Update方法
                method = new CodeMemberMethod();
                //方法名
                method.Name = "Update";
                commentText = "\n/ <summary>\n" +
                                       "/ 根据指定字段修改数据\n" +
                                       "/ <param name=\"updateColumn\">要修改数据的列</param>\n" +
                                       "/ <param name=\"conditionColumn\">修改条件列</param>\n" +
                                       "/ </summary>";
                method.Comments.Add(new CodeCommentStatement(commentText));
                //访问类型
                method.Attributes = MemberAttributes.Public | MemberAttributes.Static;
                //添加一个参数
                method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "updateColumn"));
                method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "conditionColumn"));
                //设置返回值类型:int/不设置则为void
                //method.ReturnType = new CodeTypeReference(typeof(int));
                method.ReturnType = new CodeTypeReference();
                //设置返回值
                methodCode ="             if (ConditionColumn.Trim() == \"\")\n"+
                            "                return;\n"+
                            "            if (updateColumn.Trim() == \"\")\n"+
                            "                return;\n"+
                            "            PXPublic.MyDataSet outDs = new PXPublic.MyDataSet();\n"+
                            "            string sql_set = \" SET \";\n"+
                            "            string sql_where = \" WHERE 1=1 \";\n"+
                            "            \n"+
                            "            if (updateColumn.Trim().Contains(\",\"))\n"+
                            "            {\n"+
                            "                string[] updateColumn_temp = ConditionColumn.Split(',');\n"+
                            "                foreach (string column in updateColumn_temp)\n"+
                            "                {\n"+
                            "                    // 获取当前类中的所有属性\n"+
                            "                    Type t = this.GetType();\n"+
                            "                    PropertyInfo[] info = t.GetProperties();\n"+
                            "                    // 判断当前传入的条件列是否属于当前类的属性(相当于判断当前传入列是否属于数据表字段)\n"+
                            "                    // 属于则获取到当前属性的值\n"+
                            "                    foreach (PropertyInfo preperty in info)\n"+
                            "                    {\n"+
                            "                        if (column == preperty.Name)\n"+
                            "                        {\n"+
                            "                            sql_set += string.Format(column + \" = @\" + column);\n"+
                            "                            object temp = preperty.GetValue(this, null);\n"+
                            "                            PXPublic.DBManager.ParameterAdd(column, preperty.GetValue(this, null));\n"+
                            "                        }\n"+
                            "                    }\n"+
                            "                }\n"+
                            "            }\n"+
                            "            else\n"+
                            "            {\n"+
                            "            }\n"+
                            "            if (ConditionColumn.Trim().Contains(\",\"))\n"+
                            "            {\n"+
                            "                string[] ConditionColumn_temp = ConditionColumn.Split(',');\n"+
                            "                foreach (string column in ConditionColumn_temp)\n"+
                            "                {\n"+
                            "                    // 获取当前类中的所有属性\n"+
                            "                    Type t = this.GetType();\n"+
                            "                    PropertyInfo[] info = t.GetProperties();\n"+
                            "                    // 判断当前传入的条件列是否属于当前类的属性(相当于判断当前传入列是否属于数据表字段)\n"+
                            "                    // 属于则获取到当前属性的值\n"+
                            "                    foreach (PropertyInfo preperty in info)\n"+
                            "                    {\n"+
                            "                        if (column == preperty.Name)\n"+
                            "                        {\n"+
                            "                            sql_where += string.Format(\" AND \" + column + \" = @\" + column);\n"+
                            "                            object temp = preperty.GetValue(this, null);\n"+
                            "                            PXPublic.DBManager.ParameterAdd(column, preperty.GetValue(this, null));\n"+
                            "                        }\n"+
                            "                    }\n"+
                            "                }\n"+
                            "            }\n"+
                            "            else\n"+
                            "            {\n"+
                            "            }\n"+
                            "            string sql = \" UPDATE  \" + tableName + sql_set + sql_where;\n"+
                            "            PXPublic.DBManager.ExcuteSelect((sql), outDs);\n"+
                            "            if (outDs.Tables[0].Rows.Count == 1)\n"+
                            "            {\n"+
                            "            }\n"+
                            "            else\n"+
                            "            {\n"+
                            "                PXPublic.SysMesgInfo.returnMsg = \"当前查询结果不唯一\";\n"+
                            "            }\n";
                method.Statements.Add(new CodeSnippetStatement(methodCode));
                ///将方法添加到myClass类中
                myClass.Members.Add(method);


                //添加Delete方法
                method = new CodeMemberMethod();
                //方法名
                method.Name = "Delete";
                commentText = "\n/ <summary>\n" +
                                "/ 根据指定字段删除数据\n" +
                                "/ <param name=\"conditionColumn\">删除条件列</param>\n" +
                                "/ </summary>";
                method.Comments.Add(new CodeCommentStatement(commentText));
                //访问类型
                method.Attributes = MemberAttributes.Public | MemberAttributes.Static;
                //添加一个参数
                method.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "conditionColumn"));
                //设置返回值类型:int/不设置则为void
                //method.ReturnType = new CodeTypeReference(typeof(int));
                method.ReturnType = new CodeTypeReference();
                //设置返回值
                methodCode =    "            if (ConditionColumn.Trim() == \"\")\n"+
                                "                return;\n"+
                                "            PXPublic.MyDataSet outDs = new PXPublic.MyDataSet();\n"+
                                "            string sql = \" DELETE FROM \" + tableName + \" WHERE 1=1  \";\n"+
                                "            if (ConditionColumn.Trim().Contains(\",\"))\n"+
                                "            {\n"+
                                "                string[] ConditionColumn_temp = ConditionColumn.Split(',');\n"+
                                "                foreach (string column in ConditionColumn_temp)\n"+
                                "                {\n"+
                                "                    // 获取当前类中的所有属性\n"+
                                "                    Type t = this.GetType();\n"+
                                "                    PropertyInfo[] info = t.GetProperties();\n"+
                                "                    // 判断当前传入的条件列是否属于当前类的属性(相当于判断当前传入列是否属于数据表字段)\n"+
                                "                    // 属于则获取到当前属性的值\n"+
                                "                    foreach (PropertyInfo preperty in info)\n"+
                                "                    {\n"+
                                "                        if (column == preperty.Name)\n"+
                                "                        {\n"+
                                "                            sql += string.Format(\" AND \" + column + \" = @\" + column);\n"+
                                "                            object temp = preperty.GetValue(this, null);\n"+
                                "                            PXPublic.DBManager.ParameterAdd(column, preperty.GetValue(this, null));\n"+
                                "                        }\n"+
                                "                    }\n"+
                                "                }\n"+
                                "            }\n"+
                                "            else\n"+
                                "            {\n"+
                                "            }\n"+
                                "            PXPublic.DBManager.ExcuteSelect((sql), outDs);\n"+
                                "            if (outDs.Tables[0].Rows.Count == 1)\n"+
                                "            {\n"+
                                "            }\n"+
                                "            else\n"+
                                "            {\n"+
                                "                PXPublic.SysMesgInfo.returnMsg = \"当前查询结果不唯一\";\n"+
                                "            }\n";
                method.Statements.Add(new CodeSnippetStatement(methodCode));
                ///将方法添加到myClass类中
                myClass.Members.Add(method);

                //添加构造方法
                //CodeConstructor constructor = new CodeConstructor();
                //constructor.Attributes = MemberAttributes.Public;
                /将构造方法添加到myClass类中
                //myClass.Members.Add(constructor);
                //添加特特性
                //myClass.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(SerializeField))));



                //创建一个代码生成器并指定语言为C sharp
                CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
                //代码生成的方法
                CodeGeneratorOptions options = new CodeGeneratorOptions();   
                options.BracingStyle = "C"; //C风格
                //是否在字段、属性、方法之间添加空白行
                options.BlankLinesBetweenMembers = true;

                //获取程序的基目录
                string path4 = System.AppDomain.CurrentDomain.BaseDirectory;

                string outputPath = path4 + tableInfo.Tables[0].Rows[i]["tableName"].ToString() + ".cs"; //该文件的输出路径
                using (StreamWriter sw = new StreamWriter(outputPath))
                {
                    //为指定的代码文档对象模型(CodeDOM) 编译单元生成代码并将其发送到指定的文本编写器,使用指定的选项。(官方解释)
                    //将自定义代码编译器(代码内容)、和代码格式写入到sw中
                    provider.GenerateCodeFromCompileUnit(unit, sw, options); //生成类
                }
            }
        }

    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值