首页 新闻 赞助 找找看

动态编译问题

0
悬赏园豆:5 [待解决问题]

直接贴代码了:

using Microsoft.CSharp;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Reflection;
using System.Text;

namespace DynamicCompiler
{
    class Program
    {
        static void Main(string[] args)
        {
            //1.CSharpCodePrivoder
            CSharpCodeProvider objCSharpCodePrivoder = new CSharpCodeProvider();

            //2.ICodeComplier
            ICodeCompiler objICodeCompiler = objCSharpCodePrivoder.CreateCompiler();

            //3.CompilerParameters
            CompilerParameters objCompilerParameters = new CompilerParameters();
            objCompilerParameters.ReferencedAssemblies.Add("System.dll");
            objCompilerParameters.GenerateExecutable = false;
            objCompilerParameters.GenerateInMemory = true;

            //4.CompilerResults
            CompilerResults cr = objICodeCompiler.CompileAssemblyFromSource(objCompilerParameters, GenerateCode());

            if (cr.Errors.HasErrors)
            {
                Console.WriteLine("编译错误");

                foreach (CompilerError err in cr.Errors)
                {
                    Console.WriteLine(err.ErrorText);
                }
            }
            else
            {
                //通过反射,调用HelloWorld的实例
                Assembly objAssembly = cr.CompiledAssembly;
                object objHelloWorld = objAssembly.CreateInstance(
                    "DynamicCompiler.Program");

                MethodInfo objMI = objHelloWorld.GetType().GetMethod("OutPut");

                Console.WriteLine(objMI.Invoke(objHelloWorld, null));

                MethodInfo objTest = objHelloWorld.GetType().GetMethod("TestFunction");

                Console.WriteLine(objTest.Invoke(objHelloWorld, null));
            }

            Console.ReadLine();
        }

        static string GenerateCode()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("using System;");
            sb.Append(Environment.NewLine);
            sb.Append("namespace DynamicCompiler");
            sb.Append(Environment.NewLine);
            sb.Append("{");
            sb.Append(Environment.NewLine);
            sb.Append("    public class Program");
            sb.Append(Environment.NewLine);
            sb.Append("    {");

            //方法1
            sb.Append(Environment.NewLine);
            sb.Append("        public string OutPut()");
            sb.Append(Environment.NewLine);
            sb.Append("        {");
            sb.Append(Environment.NewLine);
            sb.Append("             return \"Hello world!\";");
            sb.Append(Environment.NewLine);
            sb.Append("        }");

            //方法2
            sb.Append(Environment.NewLine);
            sb.Append("        public void TestFunction()");
            sb.Append(Environment.NewLine);
            sb.Append("        {");
            sb.Append(Environment.NewLine);
            sb.Append("               Console.WriteLine(\"我是改变的测试方法\");Console.ReadKey(); ");
            sb.Append(Environment.NewLine);
            sb.Append("        }");

            sb.Append(Environment.NewLine);
            sb.Append("    }");
            sb.Append(Environment.NewLine);
            sb.Append("}");

            string code = sb.ToString();
            Console.WriteLine(code);
            Console.WriteLine();

            return code;
        }

        static void TestFunction()
        {
            Console.WriteLine("我是原有测试方法");
            Console.ReadKey();
        }
    }
}

问题:

1.动态编译的时候,我在相同的命名空间和类名下定义了签名完全一样的函数,为什么不会报错?

2.执行的时候,打印出来的是“我是改变的测试方法”,那原有的那个函数呢?

有清楚地大侠么?求指导。

梦回大唐吟诗篇的主页 梦回大唐吟诗篇 | 初学一级 | 园豆:144
提问于:2016-05-05 16:20
< >
分享
所有回答(1)
0

1.为什么要报错?难道说两个程序集中的class(就算namespace也一样)就不能够重名了?

2.你动态编译后在你else中是拿的编译的程序级去反射执行指定方法,和上面回答一样,都指明了是两个不同程序级,当然不会输出你当前程序级的方法的东西了。

Daniel Cai | 园豆:10424 (专家六级) | 2016-05-06 11:55

谢谢你的回答。我只是不明白,为什么他们会编译到两个assembly里,而不是在同一个assembly里。能再解释下吗?谢谢~

支持(0) 反对(0) 梦回大唐吟诗篇 | 园豆:144 (初学一级) | 2016-05-06 14:44

@梦回大唐吟诗篇: 这几天比较忙,没来看回复,不好意思。

程序集一旦被加载就不会被卸载(不同appdomain下另当别论),这个是框架本身所决定,假设你可以对你当前程序集做修改,那么就需要在运行时感知这点并对老的程序集做卸载,但这和运行时本身是抵触的,各种type的信息及静态对象都将阻止这种事情的发生(也不应该发生),所以你写的代码实际上是生成了一个新的程序集,只是放在内存里而已。

你可以看下Assembly的几个静态方法,同样也会发现只有load这些,而没有unload。

支持(0) 反对(0) Daniel Cai | 园豆:10424 (专家六级) | 2016-05-11 09:30
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册