【问题标题】:C#: Using class from current AppDomain when compiling with CSharpCodeProviderC#:使用 CSharpCodeProvider 编译时使用当前 AppDomain 中的类
【发布时间】:2013-12-01 21:26:38
【问题描述】:

我需要在当前上下文中通过 CSharpCodeProvider 编译和执行代码,例如:

using System;
using System.CodeDom.Compiler;
using Microsoft.CSharp;

namespace ConsoleApplication1
{
    public class Program
    {
        public static void WriteMessage(string message)
        {
            Console.WriteLine(message);
        }

        static void Main(string[] args)
        {
            var compiler = new CSharpCodeProvider();
            var parms = new CompilerParameters
            {
                GenerateExecutable = false,
                GenerateInMemory = true,
            };

            parms.ReferencedAssemblies.Add("System.dll");

            var results = compiler.CompileAssemblyFromSource(parms, new string[]
            {@" using System;

                class MyClass
                {
                    public void Message(string message)
                    {
                        Program.WriteMessage(message);//Console.Write(message);
                    }               
                }"});

            if (results.Errors.Count == 0)
            {
                var myClass = results.CompiledAssembly.CreateInstance("MyClass");
                myClass.GetType().
                    GetMethod("Message").
                    Invoke(myClass, new[] {"Hello World!"});
            }
            else
            {
                foreach (var error in results.Errors)
                {
                    Console.WriteLine(error);
                }
            }
            Console.Read();
        }
    }
}

你怎么看,我尝试从编译的代码中调用Program.WriteMessage,但我只得到错误。为什么?

【问题讨论】:

  • 什么错误?发布错误!我也没有看到对 program.write 消息的引用
  • 顺便说一下,.NET 世界中的“上下文”被称为你的AppDomain

标签: c#


【解决方案1】:

问题是您编译的程序尝试使用当前 AppDomain 中的一个类 (Program),但是在编译时,它对此一无所知。为了将Program类和“编译程序”的所有其他类链接到“编译程序”中,您需要将当前AppDomain的程序集(或者,如下面的代码,所有程序集)添加到参考库在编译代码之前。 This answer 告诉你如何:

  1. 将当前AppDomain链接到编译好的程序中,然后
  2. 将程序加载到当前的 AppDomain。

具体来说,您在第 1 步中缺少此部分:

    foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
    {
        try
        {
            string location = assembly.Location;
            if (!String.IsNullOrEmpty(location))
            {
                compilerParams.ReferencedAssemblies.Add(location);
            }
        }
        catch (NotSupportedException)
        {
            // this happens for dynamic assemblies, so just ignore it. 
        }
    } 

其中compilerParams 是您的CompilerParameters 实例。您在代码中将其称为 parms

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-18
    • 1970-01-01
    • 1970-01-01
    • 2011-10-02
    • 1970-01-01
    • 2014-09-30
    • 1970-01-01
    相关资源
    最近更新 更多