• 【.net 深呼吸】细说CodeDom(3):命名空间


    在上一篇文章中,老周介绍了表达式和语句,尽管老周没有把所有的内容都讲一遍,但相信大伙至少已经掌握基本用法。在本文中,咱们继续探讨 CodeDom 方面的奥秘,这一次咱们聊聊命名空间。

    在开始之前,老周先厚着脸皮回答一位朋友的问题,有朋友问,我有一个代码文件,或者我直接把代码弄成文本,而不是生成的文档,那这些代码文本能编译吗? 当然可以了,后面老周会介绍的,如果你有兴趣,也可以自己研究研究,不难,其实蛮简单的。

    在讲解过程中,可能老周会讲到重复的知识点,希望大家理解,因为很多知识不是孤立的,都会有联系,有时候说到一个东西,可能会牵扯到其他东西,老周一般都会废话一下,就是为了让大家更加明白,有时候难免会废话一下。

    好,节目正式开播。

    了解代码结构后,大伙一定知道,在一个程序集中,可以包含若干个命名空间,然后命名空间下面包含类型列表。要生成命名空间,可以使用 CodeNamespace 类,只要指定命名空间的名字就可以声明了。

    下面代码生成一个名为 Common 的命名空间。

                CodeNamespace ns = new CodeNamespace("Common");
                CodeCompileUnit unit = new CodeCompileUnit();
                unit.Namespaces.Add(ns);
                CodeDomProvider prd = CodeDomProvider.CreateProvider("cs");
                prd.GenerateCodeFromCompileUnit(unit, Console.Out, null);

    命名空间的容器是 CodeCompileUnit ,因此需要一个 CodeCompileUnit 实例来包装一下,它有一个 Namespaces 集合。生成的代码如下图所示。

    在命名空间下,还可以添加类型,比如我加一个 Table 类。

                CodeNamespace ns = new CodeNamespace("Common");
                CodeTypeDeclaration dcl = new CodeTypeDeclaration();
                dcl.IsClass = true; // 它是类
                dcl.Attributes = MemberAttributes.Public; // 而且是公共类
                dcl.Name = "Table";
                ns.Types.Add(dcl);
                CodeCompileUnit unit = new CodeCompileUnit();
                unit.Namespaces.Add(ns);

    声明类型要用 CodeTypeDeclaration,IsClass明确它是一个类,Attributes可以设定成员的可访问性相关的属性。声明类型后,记得添加进命名空间的Types集合中。

    生成的代码如下图所示。

    这是有朋友会说,这大括号看得不太习惯,能不能让左大括号另起一行,行,可以用 CodeGeneratorOptions 来进行选项设置,比如这样。

                CodeDomProvider prd = CodeDomProvider.CreateProvider("cs");
                CodeGeneratorOptions options = new CodeGeneratorOptions();
                options.BracingStyle = "C";
                prd.GenerateCodeFromCompileUnit(unit, Console.Out, options);

    BracingStyle属性有两个字符串的可用值,Block就是上面我们看到的那种,左大括号和声明代码位于同一位;如果为C,就是让左大括号另起一行。上面代码使用了C风格,左大括号会另起一行。

    由于在组建代码文档时,不能用嵌套命名空间,所以可以分为多个命名空间处理。

                CodeNamespace ns = new CodeNamespace("SkinObjects");
                CodeNamespace nssub = new CodeNamespace("SkinObjects.Models");
                CodeCompileUnit unit = new CodeCompileUnit();
                unit.Namespaces.Add(ns);
                unit.Namespaces.Add(nssub);

    于是生成的代码如下。

    对代码文档而言,无所谓嵌套不嵌套的,都被看作一个命名空间。

    你要是真的想要生成嵌套的命名空间,也可以用这种方法来折腾。

                string code = "namespace Test
    {
    " +
                    "	namespace Coms
    	{
    
    	}
    " +
                    "}";
                CodeSnippetCompileUnit sunit = new CodeSnippetCompileUnit();
                sunit.Value = code;
    
                CodeDomProvider prd = CodeDomProvider.CreateProvider("cs");
                prd.GenerateCodeFromCompileUnit(sunit, Console.Out, null);

    生成结果如下图所示。

    CodeSnippetCompileUnit类的使用没有别的参数,只有一个字符串,它是把一整段代码的字符串直接用来生成,而不会去解析代码的结构。就算你这样:

                CodeDomProvider prd = CodeDomProvider.CreateProvider("vb");

    哪怕把生成的代码语言改为VB,它最终生成的代码还是字符串里面指定的内容。说白了就是,CodeSnippetCompileUnit 直接把原义字符用于生成,而不考虑是什么语言什么语法。

    就算你这么弄

                string code = "我是一个兵
    
    爱国爱人民。";
                CodeSnippetCompileUnit sunit = new CodeSnippetCompileUnit();
                sunit.Value = code;

    它照样把字符串原封不动地生成,而不管是什么语言什么东东,反正只认字符串。

    在一个命名空间中,经常会涉及到引入其他命名空间的事,C#中用using语句,VB中用Import语句。比如下面例子,声明的新命名空间里引入了三个其他的命名空间。

                CodeNamespace ns = new CodeNamespace("Dong");
                ns.Imports.Add(new CodeNamespaceImport("System"));
                ns.Imports.Add(new CodeNamespaceImport("System.IO"));
                ns.Imports.Add(new CodeNamespaceImport("豆腐渣项目"));
                CodeCompileUnit unit = new CodeCompileUnit();
                unit.Namespaces.Add(ns);

    CodeNamespace类有个Imports集合,其中每个CodeNamespaceImport对象用于指定引入的命名空间的名字。注意命名空间名字不要包含代码标点,比如C类的结束语中的分号,这个生成器会根据语言自动处理,你只需要写上命名空间的名字就行了。

    如果是VB,就生成这样的代码。

    如果是 C#,就会生成这样的代码。

    看到了吧,后面的分号是自动加的,示语法而定。

    如果是C++,会生成这样的代码。

    注意,这里只是引入命名空间而已,不是引用的程序集,一定要区分清楚。如果你要引用某个程序集,应当在 CodeCompileUnit 类上设置,它有个ReferencedAssemblies集合,用一个字符串来表示引用的程序集。

    对于GAC或.NET中的程序集,直接写名字就可以了,不用加上.dll,比如System。mscorelib不必引用,一般是默认添加的。如果要引用其他程序集,可以这样写。

                CodeCompileUnit unit = new CodeCompileUnit();
                unit.ReferencedAssemblies.Add("System");
                unit.ReferencedAssemblies.Add("System.ServiceModel");
                unit.ReferencedAssemblies.Add("abcdef.dll");

    好了,今天就只介绍了命名空间的生成,顺着这个层次,下一篇文章就讲一下类型的定义。

    也许老周写得不好,大家就当娱乐节目看,有参考价值就好。

  • 相关阅读:
    Nginx.conf 配置文件详细说明
    CentOs中iptables配置允许mysql远程访问
    CentOS 6.4下编译安装MySQL 5.6.14
    CentOS6.4下Mysql数据库的安装与配置
    让nginx支持.htaccess文件实现伪静态的方法!
    MySQL导入.sql文件及常用命令
    PHP里10个鲜为人知但却非常有用的函数
    Nginx配置文件详细说明
    linux 开机启动nginx
    Redhat系列使用ISO或者光盘制作yum本地安装源
  • 原文地址:https://www.cnblogs.com/tcjiaan/p/6184312.html
Copyright © 2020-2023  润新知