【问题标题】:Runtime compilation generates a file that can't be removed运行时编译生成无法删除的文件
【发布时间】:2012-06-09 12:23:41
【问题描述】:

我有这个控制台类型的东西,它接受一行 C# 代码,将它包装在一些周围的代码中并将它编译成一个程序集。然后,我从该程序集中调用方法,输出结果,就是这样。

问题是,程序集需要有一个名称,以便我可以将其设置为朋友程序集,以便它可以访问非公共类。我将其命名为“控制台”。

一切都按预期工作,但问题是我无法在一个脚本完成后运行第二个脚本,因为名为“console”的文件已经存在于目录中并且无法被覆盖。

我已经尝试过处理具有 Dispose 方法的所有内容。我尝试使用 File.Delete 手动删除文件。没有任何帮助。

这是我正在使用的代码。我希望有人可以帮助我。

CSharpCodeProvider provider = new CSharpCodeProvider();
var param = new CompilerParameters();
param.GenerateInMemory = false;
param.GenerateExecutable = false;
param.OutputAssembly = "console";
param.ReferencedAssemblies.Add("System.dll");
param.ReferencedAssemblies.Add("System.Core.dll");
param.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location);
var results = provider.CompileAssemblyFromSource(param,
@"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace FireflyGL
{
class DebugConsole
{
    static void Run(StringWriter writer)
    {
        var stdOut = Console.Out;
        Console.SetOut(writer);
        " + input.Text + @"
        Console.SetOut(stdOut);
    }
}
}");
            if (results.Errors.HasErrors)
            {
                for (int i = 0; i < results.Errors.Count; ++i)
                {
                    PushText(results.Errors[i].ErrorText);
                }
            }
            else
            {
                try
                {
                    var writter = new StringWriter();
                    results.CompiledAssembly.GetType("FireflyGL.DebugConsole").GetMethod("Run", BindingFlags.Static | BindingFlags.NonPublic).Invoke(null, new object[] { writter });
                    PushText(writter.ToString());
                    history.Add(input.Text);
                    currentHistory = history.Count;
                    input.Text = "";
                    writter.Dispose();
                }
                catch (Exception)
                {

                }
            }
            provider.Dispose();
            File.Delete(results.CompiledAssembly.Location);

【问题讨论】:

    标签: c# runtime-compilation


    【解决方案1】:

    您必须卸载程序集才能删除所有引用。不幸的是,你不能这样做。但是,您可以卸载 AppDomain 并提供您在该 AppDomain 中引用您的程序集,它也会被卸载。

    如果您不关心造成内存泄漏,您也可以为您的程序集创建唯一名称(console1console2 等)...

    【讨论】:

    • 我确实在网上看到了一个使用 AppDomain 的示例,但我不太明白如何使用。如何让我的程序集在某个 AppDomain 中被引用?
    • 没关系。我在这里找到了答案:stackoverflow.com/questions/1799373/…
    • 还有其他方法吗?我一直在玩,AppDomain 给我带来了很多麻烦。我需要能够将对象引用发送到脚本,但它会抛出一个奇怪的“对象不可序列化”异常。
    • @Darwin,对不起,我自己对 AppDomains 了解不够。不过,您的对象需要派生自一个特殊的基类。是MarshalByRef吗?
    • 这就是我寻找其他选择的原因,因为我无法让所有东西都来自 MarshalByRef。
    猜你喜欢
    • 2018-04-05
    • 1970-01-01
    • 2018-04-16
    • 1970-01-01
    • 2020-10-03
    • 1970-01-01
    • 2015-05-09
    • 2022-11-04
    • 2017-06-02
    相关资源
    最近更新 更多