在运行时,我希望能够卸载DLL并重新加载它的修改版本.我的第一个实验陷入了火焰之中.谁能告诉我为什么?
private static void Main()
{
   const string fullPath = "C:\\Projects\\AppDomains\\distrib\\MyLibrary.dll";

   // Starting out with a  version of MyLibrary.dll which only has 1 method,named Foo()
   AssemblyName assemblyName = AssemblyName.GetAssemblyName(fullPath);
   AppDomain appDomain = AppDomain.CreateDomain("MyTemp");
   appDomain.Load(assemblyName);
   appDomain.DomainUnload += appDomain_DomainUnload;
   AppDomain.Unload(appDomain);

   // Breakpoint here; swap out different version of MyLibrary.dll which only has 1 method,named Goo()
   AssemblyName assemblyName2 = AssemblyName.GetAssemblyName(fullPath);
   AppDomain appDomain2 = AppDomain.CreateDomain("MyTemp2");
   Assembly asm2 = appDomain2.Load(assemblyName2);

   foreach (Type type in asm2.GetExportedTypes())
   {
      foreach (MemberInfo memberInfo in type.GetMembers())
      {
         string name = memberInfo.Name;
         // Breakpoint here: Found Foo and but no Goo! I was expecting Goo and no Foo.
      }
   }
}

private static void appDomain_DomainUnload(object sender,EventArgs e)
{
   // This gets called before the first breakpoint
}

编辑:

好的,这显然是我第一次发帖.感谢Daniel格式化我的代码(我现在看到工具栏按钮,以及预览窗格!).我没有找到一种方法来回复那些要求澄清原始帖子或1个答案的人回复“评论”,所以我只是发布另一个“答案”来保持对话的进行. (赞赏如何完成评论的指针将不胜感激).

对帖子的评论:
Mitch – 陷入了火焰之中,因为我的foreach循环应该迭代修改后的DLL中的类型,而不是先前加载/卸载的类型.
马修 – 这可能会奏效,但我真的需要相同文件名的情况才能奏效.
迈克二 – 没有强烈的名字.

评论答案:
蓝色& Mike Two – 我会提出你的建议,但首先我需要了解一个关键方面.我已经读过你必须注意不要将程序集拉入主应用程序域,并且代码以前在卸载之前有一个foreach循环的副本.因此,怀疑访问MethodInfos是将程序集吸入主应用程序域,我删除了循环.那时我知道我需要寻求帮助,因为第一个DLL仍然无法卸载!

所以我的问题是:以下代码段中的内容导致主应用程序域直接(或间接)访问dll中的任何内容…为什么它会导致程序集也加载到主应用程序域中:

appDomain.Load(assemblyName);
appDomain.DomainUnload += appDomain_DomainUnload;
AppDomain.Unload(appDomain);

没有给我很大的信心我实际上能够在卸载之前使用DLL.

编辑2:

Mike Two – 感谢您的坚持……从DoCallBack中加载程序集是秘诀.对于任何感兴趣的人,这里有一些可能有用的信息:

听起来没有人能真正重现我的条件.为了演示原始问题,我以这种方式生成了我的dll:1.将类库项目添加到解决方案2.使用Foo构建版本1.0.0;将生成的程序集重命名为MyLibrary.dll.f. 3.将Foo重命名为Goo并构建另一个版本1.0.0;将生成的程序集重命名为MyLibrary.dll.g. 4.从解决方案中删除项目.在开始运行之前,我删除了.f并运行到断点(卸载后的第一行).然后我重新启动了.f并从另一个dll中移除了.g并运行到下一个断点. Windows并没有阻止我重命名.注意:虽然这是更好的练习,但我没有更改版本号,因为我不想假设我的客户总是这样,因为AssemblyInfo中的默认条目不是通配符版本.这似乎是一个丑陋的案件.

此外,我刚刚发现了一些可以早日让我了解的东西:

AssemblyName assemblyName = AssemblyName.GetAssemblyName(FullPath);
 AppDomain appDomain = AppDomain.CreateDomain("MyTemp");
 appDomain.Load(assemblyName);
 Assembly[] tempAssemblies = appDomain.GetAssemblies();
 // MyLibrary.dll has been loaded into the temp domain...good
 Assembly[] mainAssemblies = AppDomain.CurrentDomain.GetAssemblies();
 // MyLibrary.dll has been loaded into the main domain,too...bad!

所以我不确定AppDomain.Load的重点是什么,但它似乎也有加载程序集到主应用程序域的额外副作用.使用这个实验,我可以看到Mike Two的解决方案只将它加载到temp域中:

AppDomain appDomain = AppDomain.CreateDomain("MyTemp");
 appDomain.DoCallBack(CallBackDelegate);  // Executes Assembly.LoadFrom
 Assembly[] tempAssemblies = appDomain.GetAssemblies();
 // MyLibrary.dll has been loaded into the temp domain...good
 Assembly[] mainAssemblies = AppDomain.CurrentDomain.GetAssemblies();
 // MyLibrary.dll has NOT been loaded into the main domain...great!

那么,Mike Two,这个StackOverflow新手究竟是如何将你的答案标记为“已接受”的?或者我可以不这样做,因为我只是这里的客人?

现在我要学习如何在不将程序集吸入主应用程序域的情况下实际使用MyLibrary.谢谢大家的参与.

编辑3:

BlueMonkMN – 我继续前进并取消了活动订阅并得到了相同的结果.完整的程序现在列在下面:

const string fullPath = "C:\\Projects\\AppDomains\\distrib\\MyLibrary.dll";

 // Starting out with a  version of MyLibrary.dll which only has 1 method,named Foo()
 AssemblyName assemblyName = AssemblyName.GetAssemblyName(fullPath);
 AppDomain appDomain = AppDomain.CreateDomain("MyTemp");
 appDomain.Load(assemblyName);
 AppDomain.Unload(appDomain);

 // Breakpoint here; swap out different version of MyLibrary.dll which only has 1 method,named Goo()
 AssemblyName assemblyName2 = AssemblyName.GetAssemblyName(fullPath);
 AppDomain appDomain2 = AppDomain.CreateDomain("MyTemp2");
 Assembly asm2 = appDomain2.Load(assemblyName2);

 foreach (Type type in asm2.GetExportedTypes())
 {
    foreach (MemberInfo memberInfo in type.GetMembers())
    {
       string name = memberInfo.Name;
       // Breakpoint here: Found Foo and but no Goo! I was expecting Goo and no Foo.
    }
 }

似乎应该没有办法将程序集拉入这两行之间的主应用程序域:

appDomain.Load(assemblyName); 
AppDomain.Unload(appDomain);

解决方法

我试图复制这个.在加载的DLL(MyLibrary.dll)中我构建了两个版本.第一个类有一个名为Foo的方法,版本号为1.0.0.0.第二个具有相同的类,但该方法已重命名为Bar(我是传统主义者),版本号为2.0.0.0.

我在卸载调用后放了一个断点.然后我尝试在第一个版本的顶部复制第二个版本.我认为这就是你正在做的事情,因为路径永远不会改变. Windows不允许我在版本1上复制版本2.dll已被锁定.

我使用DoCallback更改了代码以使用在AppDomain中执行的代码加载dll.那很有效.我可以交换dll并找到新方法.这是代码.

class Program
{
    static void Main(string[] args)
    {
        AppDomain appDomain = AppDomain.CreateDomain("MyTemp");
        appDomain.DoCallBack(loadAssembly);
        appDomain.DomainUnload += appDomain_DomainUnload;

        AppDomain.Unload(appDomain);

        AppDomain appDomain2 = AppDomain.CreateDomain("MyTemp2");
        appDomain2.DoCallBack(loadAssembly);
    }

    private static void loadAssembly()
    {
        string fullPath = "LoadMe1.dll";
        var assembly = Assembly.LoadFrom(fullPath);
        foreach (Type type in assembly.GetExportedTypes())
        {
            foreach (MemberInfo memberInfo in type.GetMembers())
            {
                string name = memberInfo.Name;
                Console.Out.WriteLine("name = {0}",name);
            }
        }
    }

    private static void appDomain_DomainUnload(object sender,EventArgs e)
    {
        Console.Out.WriteLine("unloaded");
    }
}

我没有强烈的名称组装.如果你这样做,你可能会发现第一个缓存.您可以通过从命令行运行gacutil / ldl(列表下载缓存)来判断.如果你确实发现它被缓存运行gacutil / cdl来清除下载缓存.

c# – 我的应用域名不会卸载的更多相关文章

  1. ios – 重命名Xcode项目后出现NSKeyedUnarchiver错误

    解决方法不要更改项目名称.只需更改显示名称即可.它是Info.plist中的“Bundledisplayname”条目.您可能需要添加条目.如果要更改OSX应用程序的显示名称,请参阅thisanswer.

  2. 无法重命名Xcode 4中的组文件夹

    我今天在Xcode4中添加了一个新的组,其中包含几个文件.由于某种原因,这已经包含了一段时间,我无法命名或重命名组文件夹.以前有人发生过这种情况吗?解决方法你为了重命名而尝试做什么?上下文菜单不提供重命名选项.所以我也是>选择组>点击返回选择它进行编辑要么>选择组>短暂的延迟再次单击它

  3. xcode – 批量重命名我的类以更改我的项目前缀?

    Xcode现在不知道我的文件在哪里.为了解决这个问题,我打开了.pbxproj文件并进行了另一次仔细搜索和替换.这是一个涉及的过程,我希望有一个工具或Xcode功能来帮助我做到这一点,但唉,还没有.

  4. Xcode和SVN:无法重命名我的类 – >错误:155007(路径不是工作副本目录)

    我读了this.我也发现了类似的problem.但到目前为止还没有解决方案.解决方法我遇到了同样的问题,谷歌指导我这个问题,所以为迟到的’回答’道歉.无论如何,我正在研究eclipse3.5,macosx雪豹,你似乎也在使用macosx?关键是,macosx’hfs-filesystem大多数情况下设置不区分大小写,所以因为你只是想改变文件名的大小写,这可能是你的问题.我的解决方法是从FOO.h到Foo.h执行重命名:>FOO.h–>foobar.h中>FooBar.h–>foo.h中

  5. 【译】哥们儿,我的方法哪儿去了?

    想象有一天你正在给Swift编译器喂一些看起来无害的代码。然后一个冲击波打来:它们哪儿去了?让我再加点方便方法吧。

  6. Swift测试给出错误“架构x86_64的未定义符号”

    我正在从命令行运行swift测试来运行测试用例。问题是main.swift的存在指示构建工具生成可执行文件,并且链接可执行文件不能很好地工作。重命名后,必须注释if代码,因为全局运行代码只能属于main.swift。

  7. 使用Android Studio重命名Android包名称

    我创建了一个包含com.example包的Android应用程序.******.pample.我需要将包名重构为org.newOrg.*******.样本.我已经尝试过重构方法.但它的父母“com”并没有变成“org”.告诉我重构整个包名的任何解决方案.提前致谢解决方法此修改需要三个步骤:>更改清单中的包名称>右键单击重构包名称–>重构–>在树视图中重命名,然后Android工作室将显示一个窗口,

  8. Android Studio重命名属性或方法并不总是有效

    在AndroidStudio中,我有时必须重命名一些字段,属性或方法名称.我知道我必须选择它的名字,然后点击AltShiftR.然后我输入新名称,然后点击Enter.然而,有时它有效,有时……解决方法我怀疑你错过了重构预览窗口,当AS找到一些它不知道是否应该重构的代码时,它会显示出来.例如,如果在注释中引用了被修改的方法,那么AS将询问您是否也要重构这些注释.

  9. android – File.renameTo()返回true,但文件尚未重命名

    我正在尝试为我的录音机创建一个文件,但是这个文件不断获得一个随机名称.因为这很难处理,所以我希望在使用更有意义的名称创建文件后重命名该文件.但是,即使renameto返回true,该文件仍未重命名.我在这里做错了吗?

  10. 建议在Android studio中重命名Android项目(基于Gradle)

    在我目前的项目中,我希望在Android工作室(0.8.9)中重命名Android项目,并希望在以后使用它.我知道在论坛中讨论的2个解决方案.有人可以确认最佳方法并且无忧无虑.此外,在Androidstudio0.8.9上尝试/测试的任何建议都是最好的.我知道的解决方案(但不确定)A.-关闭正在考虑的项目.复制它并重命名为新名称并使用Androidstudio打开.在这种情况下–项目.iml文件仍

随机推荐

  1. c# – (wpf)Application.Current.Resources vs FindResource

    所以,我正在使用C#中的WPF创建一个GUI.它看起来像这样:它现在还没有完成.这两行是我尝试制作一种数据表,它们在XAML中是硬编码的.现在,我正在C#中实现添加新的水果按钮功能.我在XAML中有以下样式来控制行的背景图像应该是什么样子:因此,在代码中,我为每列col0,col1和col2创建一个图像,如果我使用以下代码,它添加了一个如下所示的新行:如你所见,它不太正确……为什么一个似乎忽略了一些属性而另一个没有?

  2. c# – 绑定DataGridTemplateColumn

    似乎我已经打了个墙,试图在DataGrid上使用DataTemplates.我想要做的是使用一个模板来显示每个单元格的两行文本.但是似乎无法以任何方式绑定列.以下代码希望显示我想做的事情.注意每个列的绑定:模板列没有这样的东西,因此,这个xaml不可能工作.我注定要将整个DataTemplate复制到每个列,只是对每个副本都有不同的约束?解决方法我不完全确定你想要做什么,但如果您需要获取整行的DataContext,可以使用RelativeSource绑定来移动视觉树.像这样:

  3. c# – 学习设计模式的资源

    最近我来到了这个设计模式的概念,并对此感到非常热情.你能建议一些帮助我深入设计模式的资源吗?

  4. c# – 是否有支持嵌入HTML页面的跨操作系统GUI框架?

    我想开发一个桌面应用程序来使用跨系统,是否有一个GUI框架,允许我为所有3个平台编写一次代码,并具有完全可脚本化的嵌入式Web组件?我需要它有一个API来在应用程序和网页之间进行交流.我知道C#,JavaScript和一些python.解决方法Qt有这样的事情QWebView.

  5. c# – 通过字符串在对象图中查找属性

    我试图使用任意字符串访问嵌套类结构的各个部分.给出以下(设计的)类:我想要从Person对象的一个实例的“PersonsAddress.HousePhone.Number”获取对象.目前我正在使用反思来做一些简单的递归查找,但是我希望有一些忍者有更好的想法.作为参考,这里是我开发的(crappy)方法:解决方法您可以简单地使用标准的.NETDataBinder.EvalMethod,像这样:

  6. c# – 文件下载后更新页面

    FamilyID=0a391abd-25c1-4fc0-919f-b21f31ab88b7&displaylang=en&pf=true它呈现该页面,然后使用以下元刷新标签来实际向用户提供要下载的文件:你可能需要在你的应用程序中做类似的事情.但是,如果您真的有兴趣在文件完全下载后执行某些操作,那么您的运气不佳,因为没有任何事件可以与浏览器进行通信.执行此操作的唯一方法是上传附件时使用的AJAXupload.

  7. c# – 如何在每个机器应用程序中实现单个实例?

    我必须限制我的.net4WPF应用程序,以便每台机器只能运行一次.请注意,我说每个机器,而不是每个会话.我使用一个简单的互斥体实现单实例应用程序,直到现在,但不幸的是,这样一个互斥是每个会话.有没有办法创建机器互连,还是有其他解决方案来实现每个机器应用程序的单个实例?

  8. c# – WCF和多个主机头

    我的雇主网站有多个主机名,都是同一个服务器,我们只是显示不同的皮肤来进行品牌宣传.不幸的是,在这种情况下,WCF似乎不能很好地工作.我试过overridingthedefaulthostwithacustomhostfactory.这不是一个可以接受的解决方案,因为它需要从所有主机工作,而不仅仅是1.我也看过thisblogpost,但是我无法让它工作,或者不是为了解决我的问题.我得到的错误是“这

  9. c# – ASP.NET MVC模型绑定与表单元素名称中的虚线

    我一直在搜索互联网,试图找到一种方式来容纳我的表单元素的破折号到ASP.NET的控制器在MVC2,3或甚至4中的默认模型绑定行为.作为一名前端开发人员,我更喜欢在我的CSS中使用camelCase或下划线进行破折号.在我的标记中,我想要做的是这样的:在控制器中,我会传入一个C#对象,看起来像这样:有没有办法通过一些正则表达式或其他行为来扩展Controller类来适应这种情况?我讨厌这样的事实,我必须这样做:甚至这个:思考?

  10. c# – 用户界面设计工具

    我正在寻找一个用户界面设计工具来显示文档中可能的GUI.我不能生成代码.我知道MicrosoftVisio提供了一个功能.但有什么办法吗?您使用哪种软件可视化GUI?

返回
顶部