简体   繁体   中英

Unloading AppDomain

Is there a way to unload parent 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. When I am loading the assembly in the new AppDomain I am showing the correct path.
Or maybe there is another way I can do that?

Thanks in advance.

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




Code 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:

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").

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.

Then inside DoCallBack() method you'll call this bootstrapper instead.

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.

What you can do, however, is load both versions of the ServiceStack assembly in two child domains. 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).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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