C# 运用(codeDom和反射技术)动态编译dll ,动态调用

      在软件运用工程中,往往会根据各种各样,花样百出的需求来设计软件,在最近的项目中无意中,我就遇到了一个需求,据说是,客户要动态编译dll ,我“滴个乖乖”,这是要逆天啊!

话不多说,直接来点干货。

简单分享一下个小demo:

1.运用codeDom技术实现动态程序集编译。


                string strExpre = "using System;" +
                                  "using System.Collections.Generic;" +
                                  "using System.Linq;" +
                                   "using System.Web; " +
                                   "namespace 特殊字符.Dll.Ver" + newVer + " " +
                                    "{" +
                                        "public class Test" +
                                            "{" +
                                            "" + newStr + "" +
                                            "}" +
                                    " }";
                CSharpCodeProvider cs = new CSharpCodeProvider();//创建代码生成器

                ICodeCompiler cc = cs.CreateCompiler();//实现并创建代码编译器实例

                CompilerParameters cp = new CompilerParameters();//编译器的实例参数

                cp.GenerateExecutable = false;//是否生成.exe

                cp.ReferencedAssemblies.Add("System.dll");//加载所需的dll

                cp.ReferencedAssemblies.Add("System.Core.dll");


                cp.OutputAssembly = path;


                CompilerResults cr = cc.CompileAssemblyFromSource(cp, strExpre);

               


                if (cr.Errors.HasErrors)

                {

                    //  Console.WriteLine(cr.Errors.ToString());
                    Directory.Delete(HttpContext.Current.Server.MapPath(dir));
                    throw new Exception();

                }

                else

                {

}

2.运用反射技术,根据程序集实例化类,并调用方法


                    //Assembly ass = cr.CompiledAssembly;//动态编译程序集(只限于动态,当程序连续动态编译时只能加载出程序上次启动得dll文件)
                    //新编译出的文件路径
                    string newComplierPath = HttpContext.Current.Server.MapPath(@"Dll\Ver" + newVer.ToString() + @"\Test.dll");

                    Assembly ass = Assembly.LoadFile(newComplierPath);

                    object obj = ass.CreateInstance("特殊字符.Dll.Ver" + newVer + ".Test");

                    MethodInfo mi = obj.GetType().GetMethod("save");

                    resulta = (int)mi.Invoke(obj, new object[] { num });

3.前端参数:

string newStr=public int save(int a){int b=a; return b;};

4.直接上完整代码:

using Microsoft.CodeDom.Providers.DotNetCompilerPlatform;
using Newtonsoft.Json;
using ReportSystem.DAL;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Remoting;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using 特殊字符.Model;

namespace 特殊字符
{
    /// <summary>
    /// handle 的摘要说明
    /// </summary>
    public class handle : IHttpHandler
    {

        public void ProcessRequest(HttpContext context)
        {

            int resulta = 0;
            var result = context.Request["content"];
            var num = Convert.ToInt32(context.Request["num"]);
           
            var newStr = HttpUtility.UrlDecode(result);
            
            FileVerValidate vervalidateOld =getLastVerInfo();//旧版
            string signStrNew = SHAEncryption(newStr);//当前
            if (signStrNew == vervalidateOld.signStr)
            {
                context.Response.Write("版本未变");
            }
            else
            {
                string lastVerNo = vervalidateOld.vernum;
                double newVer = Convert.ToDouble(lastVerNo) + 1;

                string dir = @"Dll\Ver" + newVer.ToString();

                if (!Directory.Exists(dir))
                {
                    Directory.CreateDirectory(HttpContext.Current.Server.MapPath(dir));
                }
                string path = HttpContext.Current.Server.MapPath(dir + @"\AccountTest.dll");

                string strExpre = "using System;" +
                                  "using System.Collections.Generic;" +
                                  "using System.Linq;" +
                                   "using System.Web; " +
                                   "namespace 特殊字符.Dll.Ver" + newVer + " " +
                                    "{" +
                                        "public class AccountTest" +
                                            "{" +
                                            "" + newStr + "" +
                                            "}" +
                                    " }";

                CSharpCodeProvider cs = new CSharpCodeProvider();

                ICodeCompiler cc = cs.CreateCompiler();

                CompilerParameters cp = new CompilerParameters();

                cp.GenerateExecutable = false;

                cp.ReferencedAssemblies.Add("System.dll");

                cp.ReferencedAssemblies.Add("System.Core.dll");


                cp.OutputAssembly = path;


                CompilerResults cr = cc.CompileAssemblyFromSource(cp, strExpre);

               


                if (cr.Errors.HasErrors)

                {

                    //  Console.WriteLine(cr.Errors.ToString());
                    Directory.Delete(HttpContext.Current.Server.MapPath(dir));
                    throw new Exception();

                }

                else

                {

                    //Assembly ass = cr.CompiledAssembly;//动态编译程序集(只限于动态,当程序连续动态编译时只能加载出程序上次启动得dll文件)
                    //新编译出的文件路径
                    string newComplierPath = HttpContext.Current.Server.MapPath(@"Dll\Ver" + newVer.ToString() + @"\AccountTest.dll");

                    Assembly ass = Assembly.LoadFile(newComplierPath);

                    object obj = ass.CreateInstance("特殊字符.Dll.Ver" + newVer + ".AccountTest");

                    MethodInfo mi = obj.GetType().GetMethod("save");

                    resulta = (int)mi.Invoke(obj, new object[] { num });

                    string sql = "insert into DynamicDllVerRecord values('" + newStr + "','" + newVer.ToString() + "','" + GetTimeStamp() + "',0,'Mr.Wang','"+DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")+"');" +
                                 "update DynamicDllVerRecord set TimeStamp='' where Id=" + vervalidateOld.Id + "";
                    int resultNum = SQLHelper.ExecuteNonQuerySQL(sql);

                }
            }
            context.Response.Write(resulta);
        }
        #region 获得上次版本信息

      
        private  FileVerValidate getLastVerInfo() {
            FileVerValidate validate = new FileVerValidate();
            string sql = "select top(1)Id,Ver,FunStr from DynamicDllVerRecord where TimeStamp<>'' order by CreateDate desc;;";
            DataTable obj=SQLHelper.ExecuteDataTableSQL(sql);

            string sql2 = "select top(1)Id,Ver,FunStr from DynamicDllVerRecord order by CreateDate desc;";
            DataTable obj2 = SQLHelper.ExecuteDataTableSQL(sql2);
            string verNo = "";
            string funStr = string.Empty;
            int id = 0;
            if (obj2.Rows.Count == 0)
            {
                verNo = "";
                funStr = "";
                id = 0;
            }
            else if (obj.Rows.Count == 0 && obj2.Rows.Count != 0)
            {
                verNo = obj2.Rows[0]["Ver"].ToString();
                funStr = obj2.Rows[0]["FunStr"].ToString();
                id= Convert.ToInt32(obj2.Rows[0]["Id"].ToString());
            }
            else if (obj.Rows.Count != 0 && obj2.Rows.Count != 0)
            {
                verNo = obj.Rows[0]["Ver"].ToString();
                funStr = obj.Rows[0]["FunStr"].ToString();
                id = Convert.ToInt32(obj.Rows[0]["Id"].ToString());
            }
            
            if (funStr != "")
            {

             

                string resturnStr = SHAEncryption(funStr);//字符传内容签名

                validate.signStr = resturnStr;

                validate.vernum = verNo;

                validate.Id = id;

            }

            return validate;
          


        }

        #endregion


        #region 数字签名dll内容

        public static string SHAEncryption(string FunStr)
        {

            byte[] bytes = Encoding.Default.GetBytes(FunStr);
            SHA1 sha = new SHA1Managed();
            byte[] result_byte = sha.ComputeHash(bytes);
            return Convert.ToBase64String(result_byte);
        }

        #endregion
        public bool IsReusable
        {
            get
            {
                return false;
            }
        }

        /// <summary> 
        /// 获取时间戳 
        /// </summary> 
        /// <returns></returns> 
        public static string GetTimeStamp()
        {
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            return Convert.ToInt64(ts.TotalSeconds).ToString();
        }
    }

    public class  FileVerValidate {

        public int Id { set; get; }

        public  string vernum { set; get; }

        public  string signStr { set; get; }
    }
}

以上代码是基于后台的角度对版本,和内容匹配,添加相关逻辑。

                                           ----------------“天行健,君子以自强不息;地势坤,君子以厚德载物”

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值