卸载应用程序域中
本文关键字:应用程序域 卸载 | 更新日期: 2023-09-27 18:16:33
是否有办法卸载父AppDomain?
我试图在我的新AppDomain中加载程序集的不同版本,但它一直从父域加载版本。当我在新的AppDomain中加载程序集时,我会显示正确的路径。
或者还有别的方法?
提前感谢。
编辑
AppDomain MailChimpDomain = AppDomain.CreateDomain("MailChimpDomain");
string path = AppDomain.CurrentDomain.BaseDirectory + "ServiceStack_V3''ServiceStack.Text.dll";
MailChimpDomain.Load(AssemblyName.GetAssemblyName(path));
EDIT2 代码2:
var MailDom = AppDomain.CreateDomain("MailChimpDomain");
MailDom.AssemblyLoad += MailDom_AssemblyLoad;
MailDom.AssemblyResolve += new ResolveEventHandler(MailDom_AssemblyResolve);
MailDom.DoCallBack(() =>
{
string name = @"ServiceStack.Text.dll";
var assembly = AppDomain.CurrentDomain.Load(name);
string name2 = @"MailChimp.dll";
var assembly2 = AppDomain.CurrentDomain.Load(name2);
//mailChimp object with API key found in mailChimp profile
MailChimp.MailChimpManager mc = new MailChimp.MailChimpManager("111111111111222f984b9b1288ddf6f0-us1");
//After this line there are both versions of ServiceStack.Text Assembly
MailChimp.Helper.EmailParameter em = new MailChimp.Helper.EmailParameter();
em.Email = strEmailTo;
//Creating email parameters
string CampaignName = "Digest for " + strEmailTo + " " + DateTime.Now.ToShortDateString();
MailChimp.Campaigns.CampaignCreateOptions opt = new MailChimp.Campaigns.CampaignCreateOptions();
opt.ListId = "l338dh";
opt.Subject = strSubject;
opt.FromEmail = strEmailFrom;
opt.FromName = strNameFrom;
opt.Title = CampaignName;
//creating email content
MailChimp.Campaigns.CampaignCreateContent content = new MailChimp.Campaigns.CampaignCreateContent();
content.HTML = strEmailContent;
//Creating new email and sending it
MailChimp.Campaigns.CampaignFilter par = null;
MailChimp.Campaigns.CampaignSegmentOptions SegOpt = null;
MailChimp.Campaigns.CampaignTypeOptions typeOpt = null;
mc.CreateCampaign("regular", opt, content, SegOpt, typeOpt);
MailChimp.Campaigns.CampaignListResult camp2 = mc.GetCampaigns(par, 0, 5, "create_time", "DESC");
foreach (var item in camp2.Data)
{
if (item.Title == CampaignName)
{
mc.SendCampaign(item.Id);
break;
}
}
});
static Assembly MailDom_AssemblyResolve(object sender, ResolveEventArgs args)
{
byte[] rawAssembly = File.ReadAllBytes(Path.Combine(path, args.Name));
return Assembly.Load(rawAssembly);
}
代码实际做的是将程序集加载到父域。如果要将程序集加载到子域,则必须从子域内部进行。这是一种先有鸡还是先有蛋的问题,因为父程序集(将子程序集加载到子域)也必须加载到子域才能执行。
假设你有一个简单的例子,你有一个控制台应用程序和一个名为MyAssembly.dll的程序集,它可以这样做:
static void Main(string[] args) {
var domain = AppDomain.CreateDomain("MailChimpDomain");
domain.AssemblyResolve +=new ResolveEventHandler(domain_AssemblyResolve);
domain.DoCallBack(() => {
string path = @"MyAssembly.dll";
var assembly = AppDomain.CurrentDomain.Load(path);
// to do something with the assembly
var type = assembly.GetType("MailChimp.MailChimpManager");
var ctor = type.GetConstructor(new[] { typeof(string) });
var mc = ctor.Invoke(new object[] { "111111111111222f984b9b1288ddf6f0" });
});
}
static Assembly domain_AssemblyResolve(object sender, ResolveEventArgs args) {
byte[] rawAssembly = File.ReadAllBytes(Path.Combine(@"c:'MyAssemblyPath", args.Name));
return Assembly.Load(rawAssembly);
}
在这种情况下,子域具有与父域相同的用于解析程序集的根目录(因此它可以执行加载"MyAssembly.dll"的代码)。
如果使用反射的代码比这个长,你可以考虑使用bootstrapper。也就是说,你创建了一个名为MyBootstrapper.dll的新库,你将直接从MyBootstrapper.dll中引用ServiceStack.Text.dll和MailChimp.dll的版本,你将创建一个名为Bootstrapper
的引导类,它将是静态的,并且将有一个名为Run
的公共静态方法来做脏工作。
然后在DoCallBack()
方法中调用这个bootstrapper。
string path = @"MyBootstrapper.dll";
var assembly = AppDomain.CurrentDomain.Load(path);
// to do something with the assembly
var type = assembly.GetType("MyBootstrapper.Bootstrapper");
var method = type.GetMethod("Run", BindingFlags.Static);
method.Invoke(null, null);
// or if the Run method has one parameter of "string" type
var method = type.GetMethod("Run", BindingFlags.Static, Type.DefaultBinder, new[] { typeof(string) }, null);
method.Invoke(null, new object[] { "Parameter to run" });
不可以,你不能卸载默认的AppDomain或在默认AppDomain中加载的任何程序集。
但是,您可以做的是在两个子域中加载ServiceStack程序集的两个版本。你应该可以卸下它们中的任何一个。然而,使用来自这些域的类型可能会比平常更加困难。你必须通过远程操作来完成。考虑到由此带来的开销,你应该考虑只使用该程序集的一个版本(即使这意味着要调整应用程序的一部分,即运行在默认域中的那个版本)。