从 byte[] 动态加载程序集
Dynamically load assembly from byte[]
我需要在运行时多次从内存中加载多个程序集。我还需要在对它们进行一些更改后 重新加载这些程序集 的可能性。
我试过标准的 Assembly.Load 方法,它工作正常,直到我意识到当我再次加载同一个程序集时,它在 [=14= 中出现了两次]
AppDomain.CurrentDomain.GetAssemblies()
由于有多个加载操作,这不是我想要完成的。我知道如果我从磁盘加载 DLL,如果它以未更改的形式存在,它将不会加载。
然后我尝试将 DLL 加载到 new AppDomain,但我遇到了依赖项问题。
这是简化的场景:
我共享了一个DLL,叫它AssemblyA,被主应用程序引用。
我还有几个要动态加载的 DLL(称它们为 AssemblyB...Z)。这些 DLL 还引用了 AssemblyA。
正如我上面提到的,我的主应用程序引用了 AssemblyA,它具有抽象 class 以及主应用程序实现的方法(称为 LoadAssemblies)。此方法用于通过新的 AppDomain 动态加载程序集的其余部分。
这是 LoadAssemblies 的当前代码(我尝试手动加载依赖项):
public override void LoadAssemblies()
{
AppDomain pluginDomain = AppDomain.CreateDomain("PluginDomain");
foreach (byte[] xmlDLL in listOfDLLS)
{
Assembly reflection = Assembly.ReflectionOnlyLoad(xmlDLL);
foreach (var dependencies in reflection.GetReferencedAssemblies())
{
if (dependencies.Name.Equals("AssemblyA"))
{
Assembly pluginr = Assembly.ReflectionOnlyLoad(AssemblyA);
foreach (var d in pluginr.GetReferencedAssemblies())
pluginDomain.Load(d);
pluginDomain.Load(plugin);
}
else
pluginDomain.Load(dependencies);
}
Assembly assembly = pluginDomain.Load(xmlDLL);
}
上面的代码在线出错
Assembly assembly = pluginDomain.Load(xmlDLL);
说它:
could not load assembly or one of its dependencies
也尝试使用 AssemblyResolver 事件,但它抱怨可序列化,然后当我使其可序列化时,抱怨类型。
PS。很遗憾,我无法将 DLL 保存在磁盘上。
我找到了解决方法。解决方案是使用:
pluginDomain.SetData("Assembly", DLLinByteArray);
pluginDomain.DoCallBack(CallbackFunction)
每当我需要在自定义 AppDomain 中执行某些操作时。
例如,对于从字节数组加载 DLL,CallbackFunction 如下所示:
byte[] assemblyToLoad = (byte[])AppDomain.CurrentDomain.GetData("Assembly");
Assembly.Load(assemblyToLoad);
如您所见,我使用 SetData 和 GetData 方法将参数发送到回调方法。
当然,为了从驻留在自定义 AppDomain 中的 DLL 调用方法,我在另一个 CallbackFunction.
中执行此操作
我需要在运行时多次从内存中加载多个程序集。我还需要在对它们进行一些更改后 重新加载这些程序集 的可能性。
我试过标准的 Assembly.Load 方法,它工作正常,直到我意识到当我再次加载同一个程序集时,它在 [=14= 中出现了两次]
AppDomain.CurrentDomain.GetAssemblies()
由于有多个加载操作,这不是我想要完成的。我知道如果我从磁盘加载 DLL,如果它以未更改的形式存在,它将不会加载。
然后我尝试将 DLL 加载到 new AppDomain,但我遇到了依赖项问题。
这是简化的场景:
我共享了一个DLL,叫它AssemblyA,被主应用程序引用。
我还有几个要动态加载的 DLL(称它们为 AssemblyB...Z)。这些 DLL 还引用了 AssemblyA。
正如我上面提到的,我的主应用程序引用了 AssemblyA,它具有抽象 class 以及主应用程序实现的方法(称为 LoadAssemblies)。此方法用于通过新的 AppDomain 动态加载程序集的其余部分。
这是 LoadAssemblies 的当前代码(我尝试手动加载依赖项):
public override void LoadAssemblies()
{
AppDomain pluginDomain = AppDomain.CreateDomain("PluginDomain");
foreach (byte[] xmlDLL in listOfDLLS)
{
Assembly reflection = Assembly.ReflectionOnlyLoad(xmlDLL);
foreach (var dependencies in reflection.GetReferencedAssemblies())
{
if (dependencies.Name.Equals("AssemblyA"))
{
Assembly pluginr = Assembly.ReflectionOnlyLoad(AssemblyA);
foreach (var d in pluginr.GetReferencedAssemblies())
pluginDomain.Load(d);
pluginDomain.Load(plugin);
}
else
pluginDomain.Load(dependencies);
}
Assembly assembly = pluginDomain.Load(xmlDLL);
}
上面的代码在线出错
Assembly assembly = pluginDomain.Load(xmlDLL);
说它:
could not load assembly or one of its dependencies
也尝试使用 AssemblyResolver 事件,但它抱怨可序列化,然后当我使其可序列化时,抱怨类型。
PS。很遗憾,我无法将 DLL 保存在磁盘上。
我找到了解决方法。解决方案是使用:
pluginDomain.SetData("Assembly", DLLinByteArray);
pluginDomain.DoCallBack(CallbackFunction)
每当我需要在自定义 AppDomain 中执行某些操作时。
例如,对于从字节数组加载 DLL,CallbackFunction 如下所示:
byte[] assemblyToLoad = (byte[])AppDomain.CurrentDomain.GetData("Assembly");
Assembly.Load(assemblyToLoad);
如您所见,我使用 SetData 和 GetData 方法将参数发送到回调方法。
当然,为了从驻留在自定义 AppDomain 中的 DLL 调用方法,我在另一个 CallbackFunction.
中执行此操作