玩转动态编译(一) 初识

动态编译的好处其实有很多,但是我发现很多人其实没有真正理解或者没有灵活运用动态编译,使得这 么强大的一个功能变成了鸡肋。在我自己使用的工具库中有很多地方都使用了动态编译,以后我会慢慢 把工具库中的代码都发布出来,所以先把动态编译的相关知识点整理了一下

什么是动态编译?

我的个人理解就是,在程序运行期间,将C#代码的字符串编译成为程序集对象,并通过反射该程 序集调用编译后的成员。

比较容易理解的一种解释就是类似于SqlServer中的

Exec

('select * from [table]')

或者Javascript中的

var a = eval("(function()

{return 1;})")

为什么要使用动态编译?

1.为了比较方便的解决一些难题

例如,计算 一个公式的字符串的值"2+3*(4-1)/5%7"

要计算这个公式的值,把他编译后直接输出无疑是 最简单有效的方法,就比如这样

//formula = 2 + 3 * (4 - 1) / 5 % 7
public decimal GetValue(string formula)
{
    string code = @"
        public class Class1
        {
            public static decimal GetValue()
            {
                return (decimal)(" + formula + @");
            }
        }
    ";
    Type type = 动态编译(code);
    return (decimal)type.GetMethod("GetValue").Invoke(null, null);
}

上面说的这种情况是最基本的一种情况,也是最容易理解的一种情况(就我个人来说是不推荐 的,因为编译一个程序集本身对资源的消耗是很大了,这种公式编译后的对象正常情况下是无法卸载的,如 果动态编译只为了使用一次是极为不明智的)

2.为了程序的性能更好

3,为了程序更灵活

4,为了更好的扩展性

5,.......

ps:2,3,4这些会在下一篇文章中提到,这里先 卖个关子。

怎么使用动态编译

先构造一个方便使用的动态编译的方法

using 

Microsoft.CSharp;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Reflection;
using System.Text;

namespace blqw
{
    public class DynamicCompile_1
    {
        /// <summary>
        ///
        /// </summary>
        /// <param name="code">需要编译的C#代码</param>
        /// <param name="usingTypes">编译代码中需要引用的类型</param>
        /// <returns></returns>
        public static Assembly CompileAssembly(string code, params Type[] usingTypes)
        {
            CompilerParameters compilerParameters = new CompilerParameters();//动态编译中使用的参数对象
            compilerParameters.GenerateExecutable = false;//不需要生成可执行文件
            compilerParameters.GenerateInMemory = true;//直接在内存中运行

            //添加需要引用的类型
            HashSet<string> ns = new HashSet<string>();//用来保存命名空间,这个对象的4.0的,如果是2.0的框架可以使用Dictionary代替

            foreach (var type in usingTypes)
            {
                ns.Add("using " + type.Namespace + ";" + Environment.NewLine);//记录命名空间,因为不想重复所以使用了HashSet
                compilerParameters.ReferencedAssemblies.Add(type.Module.FullyQualifiedName);//这个相当于引入dll
            }

            code = string.Concat(ns) + code;//加入using命名空间的代码,即使原来已经有了也不会报错的

            //声明编译器
            using (CSharpCodeProvider objCSharpCodePrivoder = new CSharpCodeProvider())
            {
                //开始编译
                CompilerResults cr = objCSharpCodePrivoder.CompileAssemblyFromSource(compilerParameters, code);

                if (cr.Errors.HasErrors)//如果有错误
                {
                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine("编译错误:");
                    foreach (CompilerError err in cr.Errors)
                    {
                        sb.AppendLine(err.ErrorText);
                    }
                    throw new Exception(sb.ToString());
                }
                else
                {
                    //返回已编译程序集
                    return cr.CompiledAssembly;
                }
            }
        }
    }
}

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索编译
, 程序
, 代码
, using
, 动态
system
c 动态编译、java 动态编译、动态编译、静态编译和动态编译、linux 编译动态库,以便于您获取更多的相关知识。

时间: 2024-09-09 01:15:47

玩转动态编译(一) 初识的相关文章

玩转动态编译(二) 实战

在玩转动态编译:一.初识中,我们已经学会了最简单的使用动态编译.今天直接由实战入手,看看 真实情况下的动态编译能为我们来带什么. 今天要演示的实例是一个在实际开发中经常遇到的情 况,对象转Json. 我将会使用2种方式分别做一个转json字符串的实例,1:反射:2:动态编译 分析问题 分析C#对象在json中的映射.总体来说json对象只有几种情况 键值对 对象,由多组键对象+值对象构成,最外面是一对花括号包裹,键值对对象同时也可作为"值对象"使用 数组对象,由多个值对象构成,最外面是

玩转动态编译(三) 提高性能,抛弃反射

通过之前2篇文章的介绍,大家一定发现了,动态编译后的对象只能通过反射调用,但是反射往往是 一个程序性能的瓶颈,这个真的无法突破么?答案当然是否定的,接下来就我就来说说怎么才能,挖掘 动态编译的潜力. 一点废话 我刚来博客园才1星期左右,昨天才弄懂怎么发表到首页,先 说声抱歉了,昨天的文章有几个地方贴的源码居然少了几个字符,有点莫名其妙,也难怪有人不能运行 了,虽然是小错误,但是如果认真检查的话也是可以避免的,这是我的失误. 还有一点,这个< 玩转动态编译>是一个系列的,虽然没有大纲,不知道会写

玩转动态编译(四) 封装

既然要使用动态编译,那么为他封装一个调用类,在调用时省去大量不必要的编码操作还是很有必要的 . 为什么要封装? 其实这个说起来很简单,就是发现现有的动态编译类在使用过程中显 得并不是那么好用.我觉得我可以让他变的更易使用. 所以我应该重新封装了一个 DynamicCompile类. 不过在这之前我还要考虑一下一个问题: 我需要什么? 在使 用动态编译的过程中,我逐渐的发现,动态编译有以下几种情况 1.我拼接了一个静态类的代码, 需要返回这个类的类型 2.我拼接了一个拥有无参构造函数的类的代码,需

.NET的动态编译与WS服务调用详解

这篇文章介绍了.NET的动态编译与WS服务调用详解,有需要的朋友可以参考一下,希望对你有所帮助       动态编译与WS服务,有关系么?今天就乱弹一番,如何使用动态编译动态生成WS服务调用的代理类,然后通过这个代理类调用WS服务.     首先,动态编译这玩意在.NET里面是非常简单的,实际上只涉及到两个类型:CodeDomProvider以及CompilerParameters他们都位于System.CodeDom.Compiler命名空间.     以下代码可将源码动态编译为一个程序集:

.NET的动态编译与WS服务调用详解_实用技巧

    动态编译与WS服务,有关系么?今天就乱弹一番,如何使用动态编译动态生成WS服务调用的代理类,然后通过这个代理类调用WS服务.    首先,动态编译这玩意在.NET里面是非常简单的,实际上只涉及到两个类型:CodeDomProvider以及CompilerParameters他们都位于System.CodeDom.Compiler命名空间.    以下代码可将源码动态编译为一个程序集:动态编译 复制代码 代码如下: CodeDomProvider provider = CodeDomPro

java笔记十一:动态编译

JDK6.0推出了动态编译的新功能,能够在程序中动态的写一个类,再对之进行编译.编译成class文件后就可以通过类加载方式把动态编译的类加载到内存中.当然也能通过RunTime类调用javac命令来动态编译. 动态编译类的主要步骤: ①.写一个字符串,这个字符串就是要编译的类的全部内容. ②.通过输出流,把该字符串的内容写到工程下面指定的包中. ③.对创建的java文件进行编译. 动态编译涉及的类有JavaCompiler.StandardJavaFileManager,具体如何编译看下面的例子

.NET中的动态编译

代码的动态编译并执行是一个.NET平台提供给我们的很强大的工具用以灵活扩展(当然是面对内部开发人员)复杂而无法估算的逻辑,并通过一些额外的代码来扩展我们已有 的应用程序.这在很大程度上给我们提供了另外一种扩展的方式(当然这并不能算是严格意义上的扩展,但至少为我们提供了一种思路). 动态代码执行可以应用在诸如模板生成,外加逻辑扩展等一些场合.一个简单的例子,为了网站那的响应速度,HTML静态页面往往是我们最好的选择,但基于数据驱动的网站往往又很难用静态页面实现,那么将动态页面生成html的工作或许

memcache: PHP动态编译出现Cannot find autoconf 动态编译PHP的memcache扩展库

PHP动态编译出现Cannot find autoconf在安装完PHP后,想动态编译PHP的memcache扩展库cd memcache-2.2.5//usr/local/webserver/php/bin/phpize./configure --with-php-config=/usr/local/webserver/php/bin/php-config但是执行/usr/local/webserver/php/bin/phpize时出现错误:  Configuring for:PHP Api

一个动态编译的例子

编译|动态|编译 using System;using System.CodeDom.Compiler;using Microsoft.CSharp;using System.Reflection;using System.Text; namespace ConsoleApplication22{ /// <summary> /// Class1 的摘要说明. /// </summary> class Class1 { /// <summary> /// 应用程序的主入