C# 内嵌脚本的研究(一)C# codeDom

引言:

勇哥想研究一下C#内嵌脚本的知识。
主要想把运动控制、视觉的一些功能封装成指令,用脚本语言进行调用。
就像机器人的vb语言,它就是把一些功能封装成指令进行调用。



CodeDom 是啥东东?Html Dom听过吧,XML Dom听过吧。DOM一般可翻译为 文档对象模型,那 Code + DOM呢,自然是指代码文档模型了。如果你从来没接触过 CodeDom,你大概可以根据这个名字,推断它应该和代码文档模型有关。


这推断是靠谱的,CodeDom的功能,归结为两大部分:


1、生成代码文档。这个听起来很玄?不玄,就是咱们在VS里常常耍的代码生成,比如你添加了一个服务引用,VS会帮你生成一个客户端代理类。

2、动态编译程序集。这个也好懂,就是动态编译。



演示程序:

using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.IO;
using System.Collections;

namespace DemoCodeDOM
{
    class Class1
    {
        [STAThread]

        static void Main(string[] args)
        {
            GenerateCode();
            System.Console.WriteLine("Generate Code OK");
            CompilerResults crt = CompileCode("GenCodeHello.cs");

            //下面是编译的结果
            // If errors occurred during compilation, output the compiler output and errors.
            if (crt.Errors.Count > 0)
            {
                for (int i = 0; i < crt.Output.Count; i++)
                    Console.WriteLine(crt.Output[i]);

                for (int i = 0; i < crt.Errors.Count; i++)
                    Console.WriteLine(i.ToString() + ": " + crt.Errors[i].ToString());
            }

            else
            {
                // Display information about the compiler's exit code and the generated assembly.
                Console.WriteLine("Compiler returned with result code: " + crt.NativeCompilerReturnValue.ToString());
                Console.WriteLine("Generated assembly name: " + crt.CompiledAssembly.FullName);

                if (crt.PathToAssembly == null)
                    Console.WriteLine("The assembly has been generated in memory.");
                else
                    Console.WriteLine("Path to assembly: " + crt.PathToAssembly);

                // Display temporary files information.
                if (!crt.TempFiles.KeepFiles)
                    Console.WriteLine("Temporary build files were deleted.");
                else
                {

                    Console.WriteLine("Temporary build files were not deleted.");
                    // Display a list of the temporary build files
                    IEnumerator enu = crt.TempFiles.GetEnumerator();
                    for (int i = 0; enu.MoveNext(); i++)
                        Console.WriteLine("TempFile " + i.ToString() + ": " + (string)enu.Current);
                }
            }
            System.Console.Read();
        }


        //生成CodeDOM图,这一步是最复杂的部分,后面生成代码与编译都是以这里的东西为蓝本
        private static CodeCompileUnit ComplieUnit()
        {
            //生成一个可编译的单元,这是最根部的东西
            CodeCompileUnit compunit = new CodeCompileUnit();
            CodeNamespace sample = new CodeNamespace("Sample");//定义一个名为Sample的命名空间

            CodeTypeDeclaration MyClass = new CodeTypeDeclaration("DemoClass");//定义一个名为DemoClass的类
            CodeEntryPointMethod Start = new CodeEntryPointMethod();//定义程序入口点,就是Main()

            //下面两句产生调用方法的语句
            CodeMethodInvokeExpression cs = new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("System.Console"),
                 "WriteLine", new CodePrimitiveExpression("Hello World!"));//这句会产生如下的C#代码 System.Console.WriteLine("Hello World!");
            CodeMethodInvokeExpression wt = new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("System.Console"),
                 "Read");//这句是 System.Console.Read();


            //下面一系列语句把上述定义好的元素联接起来
            compunit.Namespaces.Add(sample);
            sample.Imports.Add(new CodeNamespaceImport("System"));//导入System命名空间
            sample.Types.Add(MyClass);
            MyClass.Members.Add(Start);
            Start.Statements.Add(cs);
            Start.Statements.Add(wt);
            return compunit;

        }


        //根据CodeDOM产生程序代码,代码文件就是GenCodeHello.cs

        public static void GenerateCode()
        {
            CSharpCodeProvider cprovider = new CSharpCodeProvider();//当然换个Microsoft.VisualBasic.VBCodeProvider就产生VB.NET的代码
            ICodeGenerator gen = cprovider.CreateGenerator();
            StreamWriter sw = new StreamWriter("GenCodeHello.cs", false);
            gen.GenerateCodeFromCompileUnit(ComplieUnit(), sw, new CodeGeneratorOptions());
            sw.Close();
        }


        //编译源代码

        public static CompilerResults CompileCode(string filepath)
        {
            CSharpCodeProvider cprovider = new CSharpCodeProvider();
            ICodeCompiler compiler = cprovider.CreateCompiler();

            //编译参数
            CompilerParameters cp = new CompilerParameters(new string[] { "System.dll" }, filepath.Substring(0, filepath.LastIndexOf(".") + 1) + "exe", false);
            cp.GenerateExecutable = true;//生成EXE,不是DLL
            CompilerResults cr = compiler.CompileAssemblyFromFile(cp, filepath);
            return cr;
        }

    }

}


上述的产生的程序代码实际上很简单的一个东西,就是一个控制台输出“Hello Word!”,为了不让它一闪而过,什么也看不清,再加一句read()让它等在那里而已。


上面代码的主要奥秘就是在CodeCompileUnit()这个方法里,生成CodeDOM图的基本代码其实是没什么很难的东西,主要是烦而已,就是定义一些元素,然后把它们连起来。上面为了能清晰的看出生成代码的程序结构把那些Add语句从上到下的全写在一起了。


即使要生成的代码比上面这个例子复杂多了,基本的东西还是没变的,就是定义的东西多一点而已,.NET Framework提供生成的元素是非常之多,好象大多数的语言功能都有,比如上面的定义类,还可以定义结构、枚举;类里面的方法、属性、字段及构造函数;定义Attribute;事件及委托;赋值、条件(if)、循环(for)语句;变量声明;异常处理语句;甚至还可以加注释。除了那种分支选择(switch或select)、while循环及break、continue没发现外(goto倒是看到了)其他东西应有尽有,至少还没发现什么大的功能无法实现的。真的太强大了。



CodeDom的相关知识见下面的系列教程:

===============================


【.net 深呼吸】细说CodeDom(1):结构大观

https://www.cnblogs.com/tcjiaan/p/6144404.html


【.net 深呼吸】细说CodeDom(2):表达式、语句

https://www.cnblogs.com/tcjiaan/p/6156396.html


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

https://www.cnblogs.com/tcjiaan/p/6184312.html


【.net 深呼吸】细说CodeDom(4):类型定义

https://www.cnblogs.com/tcjiaan/p/6186366.html


【.net 深呼吸】细说CodeDom(5):类型成员

https://www.cnblogs.com/tcjiaan/p/6203627.html


【.net 深呼吸】细说CodeDom(6):方法参数

https://www.cnblogs.com/tcjiaan/p/6226540.html


【.net 深呼吸】细说CodeDom(7):索引器

https://www.cnblogs.com/tcjiaan/p/6244408.html


【.net 深呼吸】细说CodeDom(8):分支与循环

https://www.cnblogs.com/tcjiaan/p/6259983.html


【.net 深呼吸】细说CodeDom(9):动态编译

https://www.cnblogs.com/tcjiaan/p/6277618.html


【.net 深呼吸】细说CodeDom(10):生成异常处理语句

https://www.cnblogs.com/tcjiaan/p/6294084.html


本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年5月    »
12345
6789101112
13141516171819
20212223242526
2728293031
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864