【问题标题】:C# Unload temp Appdomain while main Appdomain uses MethodInfo from tempC# 卸载临时 Appdomain 而主 Appdomain 使用来自 temp 的 MethodInfo
【发布时间】:2016-03-12 19:06:15
【问题描述】:

我想为脚本编写一个可重新加载的汇编函数。(这样我可以更快地调试脚本)

dll 生成也可以正常加载。主要问题是,我在我的主 AppDomain 中使用我的临时 AppDomain 的功能。该 dll 似乎也链接到我的主 AppDomain,因为在程序运行时我无法删除它。 如果我从我的主 AppDomain“上下文”中删除所有 MethodInfo 引用,那么删除它就没有问题。

在这里你可以看到程序是如何工作的:

  • 从外部进程生成 DLL
  • 通过 (temp AppDomain).DoCallBack(...) 加载 DLL
  • 获取 Type & MethodInfo 并调用它。
  • AppDomain.Unload(temp AppDomain)

因此,如果我跳过第 3 步,删除 dll 就没有问题。但我无法检查函数的返回是否真的显示了更新的值(我在脚本中编辑)。

我在这里发布了每个步骤的源代码: 1.

//This actually isn`t as important for you    
Process assemblyGeneration = new Process();
    assemblyGeneration.StartInfo.FileName = AppDomain.CurrentDomain.BaseDirectory + @"lib\AssemblyCompiler.exe";
    assemblyGeneration.StartInfo.Arguments = "\"" + AppDomain.CurrentDomain.BaseDirectory + "script.dll\" \"" + source + "\" \"System.dll\"";
    assemblyGeneration.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
    assemblyGeneration.StartInfo.UseShellExecute = true;
    assemblyGeneration.Start();
    assemblyGeneration.WaitForExit();
    assemblyGeneration.Dispose();

2.

        _appDomain.DoCallBack(() =>
        {
            byte[] fileContent = File.ReadAllBytes(AppDomain.CurrentDomain.BaseDirectory + "script.dll");
            AppDomain.CurrentDomain.Load(fileContent);
        });

3.

MethodInfo info = _compiledScript.GetTypeFrom("LSCT.ScriptClass").GetMethod("DefineX");

        var func = (Func<double>) Delegate.CreateDelegate(typeof(Func<double>), info);
        double x = func();
        Console.WriteLine("Output was : " + x);

4.

AppDomain.Unload(_appDomain);

那么有没有办法解决我无法重新加载 DLL 的问题?

【问题讨论】:

    标签: c# assembly dll appdomain


    【解决方案1】:

    我想我已经解决了这个问题。也许现在有性能问题,但我还没有检查过。

    无论如何,我创建了一个继承 MarshalByRefObject 的新类,并让它从临时 AppDomain 加载。

    这是新类的代码:

    public class ProcessRunner : MarshalByRefObject
    {
        public void Run()
        {
            Type typ = null;
            foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
            {
                Type t = asm.GetType("LSCT.ScriptClass");
                if (t != null)
                {
                    typ = t;
                    break;
                }
            }
            MethodInfo info = typ.GetMethod("DefineX");
    
            var func = (Func<double>)Delegate.CreateDelegate(typeof(Func<double>), info);
            double x = func();
            Console.WriteLine("Output was : " + x);
        }
    }
    

    下面是如何从临时 AppDomain 调用它:

            ProcessRunner pr = (ProcessRunner)_appDomain.CreateInstanceFromAndUnwrap(Assembly.GetExecutingAssembly().Location, "Animation_Engine.UserInterface.Code.ProcessRunner");
            pr.Run();
    

    注意:只要您从主 AppDomain 传递任何引用(通过 例如参数)到执行类,dll将链接到您的主AppDomain 并且在主 AppDomain 结束之前无法卸载。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-12
      • 1970-01-01
      • 2011-05-24
      • 2011-01-07
      • 2010-09-12
      • 1970-01-01
      相关资源
      最近更新 更多