C# 反射和CODEDOM在项目里的一点实际应用
很早就研究过CodeDom,当时觉得挺有意思的,但是一时也想不到具体应用在哪,于是写了个DEMO就放在那里了。
昨天项目里有个地方要把一大堆值拿来计算公式,每一个值还都是需要单独计算求和,并且最后的公式还不一定,最后还需要输出所有的值,搞的我有点头大,其实也不算太麻烦,但是手工定义一大堆变量再去操作我怎么想怎么不爽,突然想起CodeDom,于是尝试了下, 果然爽多了。
首先构造类,将所有要计算的值都构造成变量,把变量的赋值加减和公式的计算都放在类的一个方法里,构造完类之后调用一下方法,该计算的就都计算完了,最后用反射输出所有值就OK了。
虽然是个简单的应用,不过还是很有感觉,嘿嘿,不写重复的东西就是爽。
private string GetSumScript(Dictionary<string, DeviceInfo> dictAllDevs) { StringBuilder classSrc = new StringBuilder(); classSrc.Append(" using System;" + Environment.NewLine); classSrc.Append(" namespace A { " + Environment.NewLine); classSrc.Append("public class TempSum{ " + Environment.NewLine);//创建temp类 List<string> propList = new List<string>(); string strSum = "public void Run(){";//temp类中的计算方法 foreach (KeyValuePair<string, DeviceInfo> item in dictAllDevs) { SumValues(ref classSrc, ref strSum, ref propList, item, 4); SumValues(ref classSrc, ref strSum, ref propList, item, 10); SumValues(ref classSrc, ref strSum, ref propList, item, 20); } strSum += "}"; classSrc.Append(strSum + Environment.NewLine); classSrc.Append("}" + Environment.NewLine); classSrc.Append("}" + Environment.NewLine); object obj = BulidClass(classSrc);//创建类,调用计算方法 return GetObjFillScript(obj);//输出计算结果 } private void SumValues(ref StringBuilder classSrc, ref string strSum, ref List<string> propList, KeyValuePair<string, DeviceInfo> item, int valueIndex) { double value = 0; string strProp = "SUMVALUE" + item.Value.Level.ToString() + item.Value.Tagindex + valueIndex.ToString();//类中的变量名 switch (valueIndex) { case 4: value = item.Value.LoadValue4; break; case 10: value = item.Value.LoadValue10; break; default: value = item.Value.LoadValue20; break; } if (!propList.Contains(strProp)) { classSrc.Append("public double " + strProp + "=" + value + ";" + Environment.NewLine);//如果不存在就声明它 propList.Add(strProp); } else { strSum += GetFormula(strProp, value, item);//存在则使用公式计算 } } private object BulidClass(StringBuilder classSrc) { string source = classSrc.ToString(); CSharpCodeProvider compiler = new CSharpCodeProvider(); CompilerParameters paras = new CompilerParameters(); paras.GenerateExecutable = false; paras.GenerateInMemory = true; CompilerResults result = compiler.CompileAssemblyFromSource(paras, source); Assembly assembly = result.CompiledAssembly; object eval = assembly.CreateInstance("A.TempSum"); MethodInfo method = eval.GetType().GetMethod("Run");//调用计算方法 object reobj = method.Invoke(eval, null); return eval; } private string GetObjFillScript(object obj) { string str = ""; Type type = obj.GetType(); foreach (FieldInfo fi in type.GetFields())//用反射输出所有值 { str += "content.add('" + fi.Name.ToUpper() + "','" + fi.GetValue(obj) + "',null);"; } return str; }