C# 卸载AppDomain

C# 卸载AppDomain,c#,.net,.net-assembly,appdomain,C#,.net,.net Assembly,Appdomain,有办法卸载父AppDomain吗? 我试图在我的新AppDomain中加载程序集的不同版本,但它一直从父域加载该版本。在新AppDomain中加载程序集时,我显示了正确的路径。 或者我还有别的方法可以做到? 提前谢谢。 编辑 编辑2 代码2: var MailDom = AppDomain.CreateDomain("MailChimpDomain"); MailDom.AssemblyLoad += MailDom_AssemblyLoad;

有办法卸载父AppDomain吗?
我试图在我的新AppDomain中加载程序集的不同版本,但它一直从父域加载该版本。在新AppDomain中加载程序集时,我显示了正确的路径。
或者我还有别的方法可以做到?

提前谢谢。
编辑


编辑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);
        }

否,您不能卸载默认AppDomain或在默认AppDomain中加载的任何程序集

但是,您可以在两个子域中加载ServiceStack程序集的两个版本。您应该能够卸载其中任何一个。然而,使用这些域中的类型可能比通常更困难。你必须通过远程处理来完成


鉴于此所造成的开销,您应该考虑只使用该程序集的一个版本(即使这意味着要修改应用程序的一部分,即在默认域中运行的应用程序)。

< p>您的代码实际上是将程序集加载到父域。若要将程序集加载到子域中,必须从子域内部执行。这是一种鸡蛋问题,因为父程序集(将子程序集加载到子域中)也必须加载到子域中才能执行

假设有一个简单的示例,即控制台应用程序和名为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”的代码)

如果使用反射的代码比这个长,则可以考虑使用引导程序来代替。 也就是说,创建名为MyBootstrapper.dll的新库时,将直接从MyBootstrapper.dll中引用ServiceStack.Text.dll和MailChimp.dll的版本,您将创建引导类-让我们将其称为

Bootstrapper
,它将是静态的,并且将有一个名为
Run
的公共静态方法,该方法将执行脏工作

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

您应该能够将不同版本的程序集加载到新的应用程序域中。想显示您当前的代码吗?@OndrejSvejdar我已经添加了用于加载程序集的代码,这种方法很有效。现在,我在新域中加载了我的程序集的两个版本,即我加载的版本和来自父域的版本。当执行需要新版本程序集的代码时,它使用父域版本。有什么想法吗?@Brezhnews-没有代码示例也很难说。@Brezhnews-如果您使用强引用(如new MailChimp.MailChimpManager),那么您使用的是父域中的程序集:),您必须使用反射。您的代码太长,无法通过反射来编写,因此我建议您为其编写引导程序并调用引导程序。我已经用这种程序集的示例用法更新了我的答案。在这之后,我如何使用引导程序从程序集中调用方法?就像在我的代码中:“mc.CreateCampaign(“regular”,opt,content,SegOpt,typeOpt);”
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" });