using System; using System.CodeDom.Compiler; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Cw_Expression { class Program { static void Main(string[] args) { string exp = "ToRound(ToDouble(I1),2)"; Test t1 = new Test(); t1.I1 = "1.9876"; var s=typeof(Test1).GetMethod("GetD"); var d=s.Invoke(t1, null);//这句报错,如何能调用起来 //Test1 是动态生成的,摘抄出来实验。 Console.ReadKey(); } } public class Test { public string I1 { get; set; } public double ToDouble(string i1) { return double.Parse(i1); } public double ToRound(double data, int num) { return Math.Round(data, num); } } public class Test1 : Test { public double GetD() { return ToRound(ToDouble(I1), 2); } } }
求解决,传入test 得到结果。
全部代码,包含动态生成
using System; using System.CodeDom.Compiler; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Cw_Expression { class Program { static void Main(string[] args) { string exp = "ToRound(ToDouble(I1),2)"; Test t1 = new Test(); t1.I1 = "1.9876"; try { var s = typeof(Test1).GetMethod("GetD"); var d = s.Invoke(t1, null); } catch (Exception ex) { } #region MyRegion var result = Expression<Test, double>(exp, t1); Console.WriteLine(result); #endregion Console.ReadKey(); } #region MyRegion static Result Expression<Source, Result>(string exp, Source t) where Source : class, new() { var source = typeof(Source); var result = typeof(Result); CodeDomProvider codeDomProvider = CodeDomProvider.CreateProvider("CSharp"); CompilerParameters compilerParameters = new CompilerParameters(); compilerParameters.ReferencedAssemblies.Add("System.dll"); compilerParameters.ReferencedAssemblies.Add(source.Assembly.Location); compilerParameters.GenerateInMemory = true; compilerParameters.TreatWarningsAsErrors = false; var namespace_Name = "Dynamic_" + Guid.NewGuid().ToString("N"); var class_Name = "DynamicClass_" + Guid.NewGuid().ToString("N"); var method_Name = "DynamicMethod_" + Guid.NewGuid().ToString("N"); var field_Name = result.FullName; if (result.IsGenericType) { Type genericTypeDefinition = result.GetGenericTypeDefinition(); if (genericTypeDefinition == typeof(Nullable<>)) { Type underlyingType = Nullable.GetUnderlyingType(result); field_Name = underlyingType.FullName + "?"; } else { Type[] genericArguments = result.GetGenericArguments(); field_Name = genericTypeDefinition.FullName.Substring(0, genericTypeDefinition.FullName.Length - 2) + "<"; Type[] array = genericArguments; foreach (Type type in array) { field_Name += type.FullName; } field_Name += ">"; } } StringBuilder sb = new StringBuilder(); sb.Append("using System;").AppendLine(); sb.Append("using ").Append(source.Namespace).Append(";").AppendLine(); sb.Append("namespace ").Append(namespace_Name).AppendLine(); sb.Append("{"); sb.Append(" public class ").Append(class_Name).Append(":").Append(source.FullName).AppendLine(); sb.Append("{").AppendLine(); sb.Append(" public ").Append(field_Name).Append(" ").Append(method_Name).Append("() ").AppendLine(); sb.Append("{").AppendLine(); sb.Append(" return ").Append(exp).Append(";").AppendLine(); sb.Append("}").AppendLine(); sb.Append("}").AppendLine(); sb.Append("}"); CompilerResults compilerResults = codeDomProvider.CompileAssemblyFromSource(compilerParameters, sb.ToString()); if (compilerResults.Errors.Count > 0) { //编译异常 } // Type type2 = compilerResults.CompiledAssembly.GetType(namespace_Name + "." + class_Name); var dd = compilerResults.CompiledAssembly.CreateInstance(namespace_Name + "." + class_Name); var ddd = dd.GetType().GetMethod(method_Name); var dddd = ddd.Invoke(t, null); return dddd == null ? default(Result) : (Result)dddd; } #endregion } public class Test { public string I1 { get; set; } public double ToDouble(string i1) { return double.Parse(i1); } public double ToRound(double data, int num) { return Math.Round(data, num); } } public class Test1 : Test { public double GetD() { return ToRound(ToDouble(I1), 2); } } }
看不明白你想干什么,哪里传入test,得到什么结果?
就报错而言,那是理所当然的,Test类型里没有那个方法。
意思就是我只有一个Test类,然后我通过动态生成代码(就是Test1)继承这个Test,然后我只有一串表达式ToRound(ToDouble(I1), 2),得计算出这个结果,I1的值只有在Test中有,所以代码摘抄出来就是上面的
@apgk: 我好像懂了。你的意思是根据一个字符串来决定实例化哪个类,对吧。这样的话得把这个字符串和这个类关联起来,可以通过配置文件,或者给类加上特殊的特性,或者可以写死,或者规定一个规范,通过字符串就可以取到类名。
建议提问的时候把问题描述清楚
@会长: 可以再刷新下,代码全部贴出来了
如果可以,建议你在test加一个GetD方法,然后test1中重写他。就不需要反射
var d=s.Invoke(t1, null);
t1应该是Test1的实例,贴出来的是t1 = new Test(),Test中没有GetD,肯定报错
重写不行的,I1没有值
@apgk: 如果用重写,就变成
Test t= new Test1() ; //或是 动态编译的Test1对象
t.l1= "1.9876";
t.GetD() ;
完全可以用Test去操作 Test1
@pencile: 代码上方,调试下就知道了