using Microsoft.CSharp; using System; using System.CodeDom.Compiler; using System.Collections.Generic; using System.Reflection; using System.Text; using Newtonsoft.Json; //using EPAModelNameSpace; //using System.Security.AccessControl; using System.IO; using System.Linq; using System.Data; using Hydro.CommonBase; using System.Text.RegularExpressions; //using System.Security.Cryptography.X509Certificates; //using Hydro.ConfigModel; namespace Hydro.CodeProvider { public class EvalResult { public EvalResult(object obj, List infos) { this.obj = obj; this.infos = infos; } public object obj; public List infos; } /// /// 使用方法: /// 示例化MyEval,传入代码片段,选择模板类型或传入自定义模板 /// [Serializable] public class Eval { int paramNum; string tempCode=null; List refs = new List(); List usings = new List(); string code; object tmp; public void SetTmp(object tmp) { this.tmp = tmp; } public void SetMethodInfo(List info) { this.mi=info[FunctionIndex]; } int FunctionIndex = -1; MethodInfo mi; public bool isInit; public string errString; //static MyEval instance; //static List mis=new List(); public static dynamic CompileTotalInstance(EvalTemplate me_temp) { var code= me_temp.Get_code(); var me = new Eval(code); //me.tmp = me.getInstance(); if (!me.isInit) { return me.errString; } else { List mis = new List(); Type type = me.tmp.GetType(); for(int i=0;i< me_temp.Count;i++) { mis.Add(type.GetMethod($"TMethod{i}")); } return new EvalResult(me.tmp,mis); } } /// /// 构造函数 /// /// 自由编写;参数:List paramArray,返回值:double; /// 用来做函数可行性测试,可以不填 public Eval(string CharpCode,int num,bool isCommon=false,EvalTemplate me_temp=null) { if (!isCommon) { this.tempCode = EvalTemplate.TempCode_function; code = CharpCode; paramNum = num; tmp = getInstance(); if (tmp is string) { isInit = false; errString = tmp.ToString(); return; } Type type = tmp.GetType(); mi = type.GetMethod("myMethod"); isInit = true; } else { FunctionIndex = me_temp.Count; CharpCode = TreatHead(CharpCode); me_temp.Add_code(CharpCode); isInit = true; } } private string TreatHead(string CharpCode) { foreach (var line0 in CharpCode.Split('\n')) { string line = line0.Trim(); if (line.ToLower().IndexOf("import") == 0) { string ass = line.ToLower().Replace("import", "").Trim().Trim(';'); this.defaultRefs.Add(GlobalPath.configPath + ass); CharpCode = CharpCode.Substring(line0.Length); } else if (line.ToLower().IndexOf("using") == 0) { string ass = line; this.usings.Add(ass); CharpCode = CharpCode.Substring(line0.Length); } else { break; } } return CharpCode; } public Eval(string code) { this.tempCode = null; this.code = code; //paramNum = num; tmp = getInstance(); if (tmp is string) { isInit = false; errString = tmp.ToString(); return; } isInit = true; } /// /// 构造 /// /// 函数的代码段 /// public Eval(string CharpCode, string tempCode=null) { CharpCode = TreatHead(CharpCode); this.tempCode = tempCode; code = CharpCode; //paramNum = num; tmp = getInstance(); if (tmp is string) { isInit = false; errString = tmp.ToString(); return; } Type type = tmp.GetType(); mi = type.GetMethod("myMethod"); isInit = true; } public List defaultRefs = new List() { "system.dll" ,"Microsoft.CSharp.dll" ,"System.Data.dll" ,"System.Windows.Forms.dll" ,"Microsoft.VisualBasic.dll" ,"System.Management.dll" ,"System.Drawing.dll" ,"System.Runtime.dll" ,"System.Collections.dll" ,"System.Linq.dll" ,GlobalPath.Path+ "Hydro.CommonBase.dll" //,GlobalPath.Path+ "Hydro.CodeProvider.dll" //,Directory.GetCurrentDirectory()+"\\"+ "CommonBase.dll" //,Directory.GetCurrentDirectory() + "\\" + "CodeProvider.dll" // ,Directory.GetCurrentDirectory() + "\\" + "HydraulicModel.dll" }; /// /// 返回函数进行调用,调用方式resultMehodInfo.Invoke(tmp, null) /// /// /// private object getInstance() { var d = new Dictionary() { { "CompilerVersion", "v4.0" }, }; CodeDomProvider csharpCodeProvider= CodeDomProvider.CreateProvider("CSharp", d); ICodeCompiler compiler = csharpCodeProvider.CreateCompiler(); CompilerParameters cp = new CompilerParameters(); defaultRefs.ForEach(refs => cp.ReferencedAssemblies.Add(refs)); cp.CompilerOptions = $"/t:library /platform:anycpu /optimize+"; cp.GenerateInMemory = true; StringBuilder sourceCode = new StringBuilder(); //return paramArray[0] + paramArray[1] * 3 + paramArray[2]; if (tempCode!=null) { sourceCode.Append(tempCode.Replace("{0}", code)); } else { sourceCode.Append(code); } //myCode.Append("}\r\n"); CompilerResults cr = compiler.CompileAssemblyFromSource(cp, sourceCode.ToString()); if (cr.Errors.Count > 0) { string errString = ""; foreach(var err in cr.Errors) { errString += err.ToString()+"\r\n"; } return $"{errString}<=====>{sourceCode}"; } Assembly assembly = cr.CompiledAssembly; object tmp = assembly.CreateInstance("CoustomEval.myLib"); return tmp; } /// /// 返回函数进行调用,调用方式resultMehodInfo.Invoke(tmp, null) /// /// /// public dynamic getResult(List paramArray, List patternArray=null,LogicModelParams param=null,GeneticParams gParam=null) { object result; result = mi.Invoke(tmp, new object[] { paramArray, patternArray, param, gParam }); return result; //return mi; } public dynamic ChangeParam(LogicModelParams param, WdnmoParam wParam,GeneticParams gParam,calcParam cParam) { if (mi == null || tmp == null) return null; dynamic r = (mi.Invoke(tmp, new object[] { param, wParam, gParam, cParam })); return r; } //public dynamic ChangeResult(LogicModelParams param, WdnmoParam wParam,GeneticParams gParam,List results) //{ // return ( mi.Invoke(tmp, new object[] { param, wParam, gParam, results })); //} /// /// 返回函数进行调用,调用方式resultMehodInfo.Invoke(tmp, null) /// /// /// public dynamic getResult(Dictionary> dict_param) { object result = mi.Invoke(tmp, new object[] { dict_param }); return result; //return mi; } /// /// 返回函数进行调用,调用方式resultMehodInfo.Invoke(tmp, null) /// /// /// public dynamic getResult(dict dict_node, dict dict_link) { object result = mi.Invoke(tmp, new object[] { dict_node,dict_link }); return result; //return mi; } /// /// 返回函数进行调用,调用方式resultMehodInfo.Invoke(tmp, null) /// /// /// public string checkMethod() { Random rand = new Random(); List paramArray = new List(); for(int i=0;i paramArray,List patternArray,LogicModelParams param=null,GeneticParams gParam=null) { {0} } } }"; static string TempCode_Total = CommonUse + @" namespace CoustomEval { [Serializable] class myLib { {0} } }"; static string functionTemp = @" public double TMethod{1}(List paramArray,List patternArray,LogicModelParams param=null,GeneticParams gParam=null) { {0} }"; public static string helpText_Set = @" [类型说明] dict:字典类对象,等价于dictionary [变量说明] dict map :引用节点类对象集合 dict map_link :链接类对象集合 [属性使用示例] obj[""type""] as string==""JUNCTION"" obj[""EN_ELEVATION""] as float==0.1f [示例] dict re = new dict(); foreach (var m in map) { string id = m.Key; dict obj = m.Value as dict; if (obj[""type""] as string==""JUNCTION"" && obj[""otype""] as string ==""Meter"") re.Add(id, obj); } return re; //节点属性清单 type //类型 JUNCTION RESERVOIR TANK otype //子类型 JUNCTION METER NOZZLE RESERVOIR TANK EN_ELEVATION //标高 EN_BASEDEMAND //基本需水量 EN_PATTERN //模式 EN_EMITTER //射流系数 EN_INITQUAL //初始水质 EN_SOURCEQUAL EN_SOURCEPAT EN_SOURCETYPE EN_TANKLEVEL EN_DEMAND EN_HEAD EN_PRESSURE EN_QUALITY EN_SOURCEMASS EN_INITVOLUME EN_MIXMODEL EN_MIXZONEVOL //节点管线清单 type //类型 CVPIPE PIPE PUMP PRV PSV PBV FCV TCV GPV otype //子类型 CVPIPE PIPE PUMP PRV PSV PBV FCV TCV GPV EN_DIAMETER EN_LENGTH EN_ROUGHNESS EN_MINORLOSS EN_INITSTATUS EN_INITSETTING EN_KBULK EN_KWALL EN_FLOW EN_VELOCITY EN_HEADLOSS EN_STATUS EN_SETTING EN_ENERGY "; public static string helpText_Function = $@" =======[对象说明]====== Values:用来存储多个时刻的计算结果值,单时刻计算值,长度为1;多时刻计算时,长度为时段数; LogicValues:通常用来存储多个时刻的设置值,初始长度模式与Values一致;也可以作为曲线使用,使用数据来源为模式系数的选项,将一段自定义曲线存入; =======[引用对象的方法]====== ①一般使用""{{标签}}""或""{{变量名称}}""来引用变量,标签和变量名称有重复时,优先判定为标签;返回的是double类型。变量的值取决于变量的数据来源决定; ②获取数组和数组中的值: -使用""{{标签[]}}""来引用变量的LogicValues,返回double[]类型。 -使用""{{标签[i]}}""来获取变量的LogicValues中的第i个值,返回double类型。 -使用""{{标签[-/+i]}}""来获取过去或未来时刻的值,返回double类型。例如{{标签[-1]}}表示获取上一时刻的值,{{标签[+1]}}表示获取下一时刻的值。 ③同样的,用""{{标签<>}}""、""{{标签}}""、""{{标签<-/+i>}}""来获取Values的相关值。 语法说明: 编译环境为.netframework4.0,支持的语法如下: 类型转换建议使用Convert.ToDouble(),例如""Convert.ToDouble(变量名称)"",或者""变量名称 as T"" 程序集框架构造如下,需要填写{{0}}中的内容: {EvalTemplate.TempCode_function} "; public static string helpText_Model = $@" 使用""{{变量名称}}""来引用变量,返回的是double类型。例如""{{XX流量}}""引用变量XX流量,变量的值取决于变量的数据来源 使用""{{变量名称[]}}""来引用变量的LogicPattern,返回double[]类型。 使用""{{变量名称[i]}}""来获取变量的LogicPattern中的第i个值,返回double类型。 编译环境为.netframework4.0,支持的语法如下: 类型转换建议使用Convert.ToDouble(),例如""Convert.ToDouble(变量名称)"",或者""变量名称 as T"" 程序集框架构造如下,需要填写{{0}}中的内容: {EvalTemplate.TempCode_PreTreat} "; List codes_Total = new List(); public int Count { get { return codes_Total.Count; } } public void Add_code(string code) { string Fcode = functionTemp.Replace("{0}", code).Replace("{1}",codes_Total.Count.ToString()); //对于Fcode中每一行的缩进进行处理 var arr = Fcode.Replace("\r\n","\n").Split('\n'); for(int i=3; i myMethod(dict map_node,dict map_link) { {0} } } } "; public static string TempCode_PreTreat = CommonUse+@" namespace CoustomEval { [Serializable] class myLib { public object myMethod(LogicModelParams param, WdnmoParam wParam,GeneticParams gParam,calcParam cParam) { {0} } } } "; } }