简体   繁体   English

卸载AppDomain

[英]Unloading AppDomain

Is there a way to unload parent AppDomain? 有没有一种方法可以卸载父AppDomain?
I am trying to load a different version of an assembly in my new AppDomain, but it keeps loading the version from the parent domain. 我正在尝试在新的AppDomain中加载程序集的其他版本,但是它一直从父域中加载该版本。 When I am loading the assembly in the new AppDomain I am showing the correct path. 当我在新的AppDomain中加载程序集时,我正在显示正确的路径。
Or maybe there is another way I can do that? 也许还有另一种方法可以做到这一点?

Thanks in advance. 提前致谢。
EDIT 编辑

AppDomain MailChimpDomain = AppDomain.CreateDomain("MailChimpDomain");
string path = AppDomain.CurrentDomain.BaseDirectory + "ServiceStack_V3\\ServiceStack.Text.dll";
MailChimpDomain.Load(AssemblyName.GetAssemblyName(path));



EDIT2 EDIT2
Code 2: 代码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);
        }

What your code actually does is it loads assembly to your parent domain. 您的代码实际执行的操作是将程序集加载到您的父域中。 If you want to load assembly into child domain you have to do it from inside child domain. 如果要将程序集加载到子域中,则必须从子域中进行。 This is kind of chicken-egg problem, because the parent assembly (which loads child assembly into child domain) has to be loaded into your child domain as well in order to be executed. 这是种鸡蛋问题,因为父程序集(将子程序集加载到子域中)也必须加载到子域中才能执行。

Assuming simple example that you have console application and assembly called MyAssembly.dll it can be done like this: 假设您有一个名为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);
}

In this case child domain has same root directory for resolving assemblies as parent domain (and thus it can execute the code which loads "MyAssembly.dll"). 在这种情况下,子域具有与父域相同的根目录来解析程序集(因此,它可以执行加载“ MyAssembly.dll”的代码)。

If the code working with reflection is longer than this, you may consider using bootstrapper instead. 如果使用反射的代码长于此长度,则可以考虑使用引导程序。 IE you create new library called MyBootstrapper.dll, you'll reference directly version of ServiceStack.Text.dll and MailChimp.dll you like from MyBootstrapper.dll, and you'll create bootstrap class - lets call it Bootstrapper that will be static and will have single public static method called Run that will do dirty work. IE即会创建一个名为MyBootstrapper.dll的新库,您将直接从MyBootstrapper.dll中引用所需的ServiceStack.Text.dll和MailChimp.dll版本,并会创建bootstrap类-将其称为Bootstrapper ,它将是静态的,将有一个名为Run公共静态方法,该方法会做脏工作。

Then inside DoCallBack() method you'll call this bootstrapper instead. 然后在DoCallBack()方法中,您将改为调用此引导程序。

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" });

No, you may not unload the default AppDomain or any assemblies loaded in the default AppDomain. 不可以,您不能卸载默认AppDomain或默认AppDomain中加载的任何程序集。

What you can do, however, is load both versions of the ServiceStack assembly in two child domains. 但是,您可以在两个子域中加载两个版本的ServiceStack程序集。 You should be able to unload either of them. 您应该能够卸载其中任何一个。 However, using types from these domains may prove more difficult than usual. 但是,使用这些域中的类型可能比平时更困难。 You'll have to do it via remoting. 您必须通过远程处理来实现。

Given the overhead imposed by this, you should consider using only one version of that assembly (even if this means adapting part of your app, the one that runs in the default domain). 考虑到由此带来的开销,您应该考虑仅使用该程序集的一个版本(即使这意味着要适应应用程序的一部分,即在默认域中运行的一部分)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM