首页新闻找找看学习计划

C#动态生成代码,有继承父类,传入父类计算得到结果,看代码

0
悬赏园豆:50 [待解决问题]
复制代码
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);
        }

    }
}
View Code
< >
分享
所有回答(2)
0

看不明白你想干什么,哪里传入test,得到什么结果?

就报错而言,那是理所当然的,Test类型里没有那个方法。

会长 | 园豆:5042 (大侠五级) | 2019-08-28 11:09

意思就是我只有一个Test类,然后我通过动态生成代码(就是Test1)继承这个Test,然后我只有一串表达式ToRound(ToDouble(I1), 2),得计算出这个结果,I1的值只有在Test中有,所以代码摘抄出来就是上面的

支持(0) 反对(0) apgk | 园豆:89 (初学一级) | 2019-08-28 11:12

@apgk: 我好像懂了。你的意思是根据一个字符串来决定实例化哪个类,对吧。这样的话得把这个字符串和这个类关联起来,可以通过配置文件,或者给类加上特殊的特性,或者可以写死,或者规定一个规范,通过字符串就可以取到类名。

建议提问的时候把问题描述清楚

支持(0) 反对(0) 会长 | 园豆:5042 (大侠五级) | 2019-08-28 11:18

@会长: 可以再刷新下,代码全部贴出来了

支持(0) 反对(0) apgk | 园豆:89 (初学一级) | 2019-08-28 11:19
0

如果可以,建议你在test加一个GetD方法,然后test1中重写他。就不需要反射

var d=s.Invoke(t1, null);
t1应该是Test1的实例,贴出来的是t1 = new Test(),Test中没有GetD,肯定报错

pencile | 园豆:448 (菜鸟二级) | 2019-08-28 12:12

重写不行的,I1没有值

支持(0) 反对(0) apgk | 园豆:89 (初学一级) | 2019-08-28 12:30

@apgk: 如果用重写,就变成
Test t= new Test1() ; //或是 动态编译的Test1对象
t.l1= "1.9876";
t.GetD() ;

完全可以用Test去操作 Test1

支持(0) 反对(0) pencile | 园豆:448 (菜鸟二级) | 2019-08-28 12:49

@pencile: 代码上方,调试下就知道了

支持(0) 反对(0) apgk | 园豆:89 (初学一级) | 2019-08-28 12:56
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册