c# - 在新的应用程序域中加载程序集
问题描述
我正在开发需要不同程序集的服务,但在编译时我们不知道哪些程序集。因此我想动态加载卸载不同的程序集。我使用此代码进行加载,
static private void ExecuteAssemblyMethod(string taskName, string className, string method)
{
//load assembly in parent application domain, the assembly can not be unloaded.
var task = Assembly.LoadFrom($"tasks\\{taskName}.exe");
var myType = task.GetType($"{taskName}.{className}");
MethodInfo myMethod = myType.GetMethod(method);
object obj = Activator.CreateInstance(myType);
myMethod.Invoke(obj, null);
}
但是我发现程序集只能通过卸载appdomain来卸载。因此它需要在不同的可以卸载的应用程序域中运行。但我没有得到这个工作。我尝试了下面的代码,但它不起作用,因为 CreateInstanceFrom 返回类型 objecthandle 而不是我预期的 object。
static private void ExecuteAssemblyMethodInAppDomain(string taskName, string className, string method)
{
//create child domain and load assembly within it. the appdomain can than be unloaded.
var dom = AppDomain.CreateDomain("taskDomain");
var task = dom.CreateInstanceFrom($"tasks\\{taskName}.exe", $"{ taskName}.{ className}");
Type myType = task.GetType();
MethodInfo myMethod = myType.GetMethod(method);
myMethod.Invoke(task, null);
AppDomain.Unload(dom);
}
解决方案
将评论后的答案更新为初始答案。
使用 Unwrap 来获得对实例的访问权的直接方法不起作用,因为反射方法返回有关代理对象的信息,而不是目标类型的底层实例。
要解决此限制,需要将“已知”类型的对象注入应用程序域,以便反射代码在应用程序域内工作。
代码:
HelperAssembly -- 包含一个简单的帮助类 Helper.cs
namespace HelperAssembly
{
public class Helper : MarshalByRefObject
{
public void CreateAndRunPlugin(string assemblyName, string typeName, string methodName)
{
var task = AppDomain.CurrentDomain.CreateInstanceFromAndUnwrap(assemblyName, typeName);
Type myType = task.GetType();
MethodInfo myMethod = myType.GetMethod(methodName);
myMethod.Invoke(task, null);
}
}
}
启动任务的例程:
private static void TestAppDomain(string taskName, string className, string methodName)
{
//create child domain and load assembly within it. the appdomain can than be unloaded.
var dom = AppDomain.CreateDomain("taskDomain");
try
{
var whelper = dom.CreateInstanceFrom("path\\to\\HelperAssembly.dll", "HelperAssembly.Helper");
var helper = (Helper)whelper.Unwrap();
helper.CreateAndRunPlugin($"path\\to\\{taskname}.exe", $"{taskName}.{className}", methodName);
return;
}
finally
{
AppDomain.Unload(dom);
}
}
推荐阅读
- javascript - 计算总和,js中对象的平均数组使用reduce或for循环
- r - 如何仅使用 tiyverse 根据行值创建列名
- json - React JS URL 错误 - “./pages/test.js 模块未找到:‘/home/Desktop/App/pages’中的‘https://....../example.json’”
- node.js - 节点路由中的 WebSocket
- scala - 在火花的窗口函数中添加新列
- java - 在java中以编程方式使用itext API将excel转换为pdf
- python - tkinter .pack(anchor="s") 功能不起作用
- python - 过滤python字典中的前3个值
- php - 具有不同重定向的php登录页面
- c# - 使用 HttpClient、客户端证书和 WinHttpHandler 向 Apple Push Notification Service 发送 HTTP/2 请求会引发 HttpRequestException