打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
玩转动态编译:一、初识

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

  • 什么是动态编译?

我的个人理解就是,在程序运行期间,将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 % 7public 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;namespace blqw.DynamicCompile_Demo{    public class Program    {        static void Main(string[] args)        {            decimal val = Calculate("2 + 3 * (4 - 1) / 5 % 7");            if (val == (decimal)(2 + 3 * (4 - 1) / 5 % 7))            {                Console.WriteLine(val);            }            else            {                Console.WriteLine("错误");            }        }        public static decimal Calculate(string formula)        {            string code = @"                public class Class1                {                    public static decimal GetValue()                    {                        return (decimal)(" + formula + @");                    }                }            ";            //第二个参数就是这个类中所有用到的类型,包括隐式类型            Type type = DynamicCompile_1.CompileAssembly(code, typeof(decimal)).GetType("Class1");            return (decimal)type.GetMethod("GetValue").Invoke(null, null);        }    }}

运行后直接就可以看到效果了,所有代码都在这里了就不提供下载了哈

期待下一篇吧

我写的文章,除了纯代码,其他的都是想表达一种思想,一种解决方案.希望各位看官不要局限于文章中的现成的代码,要多关注整个文章的主题思路,谢谢!
我发布的代码,没有任何版权,遵守WTFPL协议(如有引用,请遵守被引用代码的协议)
qq群:5946699 暗号:C#交流 希望各位喜爱C#的朋友可以在这里交流学习,分享编程的心得和快乐
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
如何用C#动态编译、执行代码
使用 c # 编译器编译代码
C#反射动态调用dll中的方法,并返回结果
.net Core 使用T4生成代码
httpManager-aaaaa
断言 异常处理类,代码更简洁了
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服