• AppDomain卸载与代理


    AppDomain卸载与代理

    涉及内容:

     

    • 反射与MEF解决方案
    • AppDomain卸载与代理
    • WinForm、WcfRestService示

     

    插件系统的基本目的是实现宿主与组件的隔离,核心是作为接驳约定的接口,宿主使用类型发现及挂载插件,以下是反射实现。

     

    创建类库项目Plugin,添加接口IPlugin:

     

     View Code

     

    创建控制台程序HostApp,添加对Plugin项目的引用,Main方法代码:

     

     View Code

     

    创建类库项目MyPlugin1,添加对Plugin项目的引用,添加Plugin1类并实现IPlugin:

     

     View Code

     

    修改该项目的属性,在“生成”选项卡中找到输出,将“输出路径”指向HostApp下的binDebug文件夹,运行。

     

     

    宿主使用无参的IPlugin子类完成组件调用。代码逻辑并不复杂但我们还有更优雅的解决方式即MEF框架,这里拿MEF的完成所需功能,组件生命周期等内容并不深入讨论,如有需求请自行MSDN。

     

    MEF框架以Import、Export特性为功能入口,修改MyPlugin项目,引用System.ComponentModel.Composition,为MyPlugin添加Export特性:

     

     View Code

     

    注意Export明确指定导出类型为IPlugin,在Plugin项目中添加类PluginProvider,引用System.ComponentModel.Composition和System.ComponentModel.Composition.Hosting,添加IEnumerable<Lazy<IPlugin>>类型只读属性并标注ImportMany特性:

     

     View Code

     

    抽象基类ComposablePartCatalog表示组件目录,子类DirectoryCatalog使用指定目录进行搜索。PluginProvider使用了当前程序运行目录作为dll路径。同时导入点所在字段或属性可以是IEnumerable<T>、IEnumerable<Lazy<T>>、IEnumerable<Lazy<T, TMetadata>>等,延迟绑定能相对降低内存开销,这里使用了第2种,接着修改Main方法:

     

     View Code

     

    运行得到同样的结果,代码更加优雅;根据需求,修改PluginProvider的导入逻辑及使用泛型版本,将得到更多的灵活性。代码文件

    前一篇文章简单展示了类型发现和MEF使用,本文初步进入AppDomain相关内容。

    CLR程序运行时会创建默认程序集容器即AppDomain,默认AppDomain不支持卸载其程序集,但CLR支持创建和卸载AppDomain,这意味着我们可以间接地通过额外的AppDomain实现插件的热插拔。

    代理AppDomain创建PluginProvider实例,该实例及其发现的IPlugin的实现需要被被默认AppDomain访问,于是发生了跨AppDomain边界的访问,PluginProvider及IPlugin的具体实现需要由MarshalByRefObject派生(更多相关内容仍然需要自行MSDN)。

    为Plugin项目添加PluginProxy类,该类负责维护上述的额外AppDomain、将PluginProvider封送回默认AppDomain。本例仅设计了单个插件容器的场景,故以单例模式实现:

     View Code

    AppDomain的创建与跨边界访问对象的成本很高,后文中默认AppDomain与插件的交互将以代理PluginProxy通知PluginProvider的方式实现。Plugin中PluginProvider小幅修改:

     View Code

    MyPlugin1中Plugin1小幅修改:

     View Code

    主程序PluginProxy由静态类属性访问,同时加入逻辑检验DLL可否在AppDomain卸载后删除,WinForm与WCFRestService示例在后续给出。代码文件

     View Code

    附求职:寻求.Net相关职位,偏向后端,目前人在北京,有意请邮件jusfr.v#gmail.com,请替换#为@,沟通后奉上简历。

  • 相关阅读:
    SQL的case when then else end语句的用法
    PR轨道工具
    Power Bi追加查询
    如何在电商平台查看历史价格
    MYSQL执行SQL出现错误:Error Code:1054.Unknown column "字段名" in 'order clause'如何解决
    Python 的基础数据类型
    整数回文转换
    N-城堡问题
    Find The Multiple
    Ecust DIV3 k进制 【暴力不断优化】
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3150087.html
Copyright © 2020-2023  润新知