【问题标题】:Load same assembly second time with clean static variables使用干净的静态变量第二次加载相同的程序集
【发布时间】:2019-11-15 00:04:27
【问题描述】:

我有一个无法修改的 .dll 库,其中包含使用许多静态变量和单例实例的类。 现在我需要所有这些类的第二个实例,并且我需要一些解决方案,它可以在不改变程序集的任何其他属性的情况下隔离某个类的实例之间的静态变量。

第二次加载同一个程序集实际上并没有再次加载它,但我发现将它读取到字节数组然后加载它,实际上解决了一半的问题:

lib.dll:

namespace lib
{
    public class Class1 : ILib
    {
        private static int i;

        public int DoSth()
        {
            return i++;
        }

        public string GetPath()
        {
            return typeof(Class1).Assembly.Location;
        }
    }
}

app.exe:

namespace test
{
    public interface ILib
    {
        int DoSth();
        string GetPath();
    }

    class Program
    {
        static void Main()
        {
            var assembly1 = Assembly.LoadFile(Path.GetFullPath(".\\lib.dll"));
            var instance1 = (ILib)assembly1.CreateInstance("lib.Class1");

            Console.WriteLine(instance1.GetPath());
            Console.WriteLine(instance1.DoSth());
            Console.WriteLine(instance1.DoSth());

            var assembly2 = Assembly.LoadFile(Path.GetFullPath(".\\lib.dll"));
            var instance2 = (ILib)assembly2.CreateInstance("lib.Class1");

            Console.WriteLine(instance2.GetPath());
            Console.WriteLine(instance2.DoSth());
            Console.WriteLine(instance2.DoSth());

            var assembly3 = AppDomain.CurrentDomain.Load(File.ReadAllBytes("lib.dll"));
            var instance3 = (ILib)assembly3.CreateInstance("lib.Class1");

            Console.WriteLine(instance3.GetPath());
            Console.WriteLine(instance3.DoSth());
            Console.WriteLine(instance3.DoSth());

            Console.Read();
        }
    }
}

返回:

C:\bin\lib.dll
0
1
C:\bin\lib.dll
2
3

0
1

静态变量重新启动,但不幸的是下一个问题是库中使用的程序集位置是空的。

我想避免将库加载到不同的 AppDomain,因为它会产生过多的跨域代码问题;有些类是不可序列化的。

我想避免在磁盘上物理复制库。

我想避免使用 IL 编织和使用 Mono.Cecil 或类似的东西,因为这太过分了。

【问题讨论】:

  • 您基本上只是出于某种原因排除了所有执行此操作的方法。
  • @TheGeneral 我希望Assembly 中有一些方法可以让我指定库的名称/来源,或者可能有一些技巧可以清除加载的程序集缓存以第二次实际加载同一个库。如果 Reflection.Emit 不会为外部库创建额外的依赖项,则可以选择它

标签: c# .net reflection static .net-assembly


【解决方案1】:

将程序集加载到单独的 AppDomain 或单独的进程中只是您拥有的明智选择。要么处理跨域/跨进程通信,要么获取没有您试图解决的问题的库版本。

如果您想从字节修复负载,您需要阅读 https://blogs.msdn.microsoft.com/suzcook/2003/09/19/loadfile-vs-loadfrom/ 周围的所有文章。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-12
    • 2011-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-18
    相关资源
    最近更新 更多