在软件运用工程中,往往会根据各种各样,花样百出的需求来设计软件,在最近的项目中无意中,我就遇到了一个需求,据说是,客户要动态编译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; }
}
}
以上代码是基于后台的角度对版本,和内容匹配,添加相关逻辑。文章来源:https://www.toymoban.com/news/detail-545251.html
----------------“天行健,君子以自强不息;地势坤,君子以厚德载物”文章来源地址https://www.toymoban.com/news/detail-545251.html
到了这里,关于C# 运用(codeDom和反射技术)动态编译dll ,动态调用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!