为自己写的程序添加插件真的是一个相当常见的功能,然而如果只是简单加载程序集然后去执行程序集中的代码,会让宿主应用程序暴露在非常危险的境地!因为只要插件能够运行任何一行代码,就能将宿主应用程序修改得天翻地覆哭爹喊娘;而根本原因,就在于暴露了整个托管堆和整个 UI 树。

如果将宿主和插件放到不同的应用程序域中,则可以解决此问题。本文将介绍跨应用程序域承载 UI 的方法,其中也包含跨域(Cross-Domain)调用方法。


 

来自于托管插件框架的辅助类

.NET Framework 自 3.5 以来推出了托管插件框架(MAF,Managed AddIn Framework),位于 System.AddIn 命名空间。其特性在于,将宿主和插件隔离在不同的应用程序域中,避免插件对宿主造成不良影响。

此命名空间中存在 FrameworkElementAdapters 类型,在 System.Windows.Presentation 程序集中,详见 FrameworkElementAdapters.cs。虽说主要用于 MAF 插件框架,但其实只需要此类型便可以实现跨应用程序域的 UI。

FrameworkElementAdapters 只有两个方法,ViewToContractAdapter 将 UI 转换成 INativeHandleContract,而 ContractToViewAdapter 将 INativeHandleContract 用一个 FrameworkElement 进行承载。

public static class FrameworkElementAdapters
{
[SecurityCritical]
public static FrameworkElement ContractToViewAdapter(INativeHandleContract nativeHandleContract);
[SecurityCritical]
public static INativeHandleContract ViewToContractAdapter(FrameworkElement root);
}

一个极简的跨域 UI Demo

首先,我们需要有一个支持跨域调用的类型,并有任意的可以用来返回 INativeHandleContract 的方法。

internal sealed class DomainX : MarshalByRefObject
{
public INativeHandleContract GetElement()
{
return FrameworkElementAdapters.ViewToContractAdapter(
new Rectangle
{
Width = 200,
Height = 100,
Fill = Brushes.ForestGreen,
});
}
}

我们需要跨域创建这个 UI 控件并得到 INativeHandleContract。

var domain = AppDomain.CreateDomain("X");
var instance = (DomainX)domain.CreateInstanceAndUnwrap(typeof(DomainX).Assembly.FullName, typeof(DomainX).FullName);
var contract = instance.GetElement();

然后,在需要承载这个跨域 UI 的地方取得这个 INativeHandleContract 的实例 contract。

var element = FrameworkElementAsyncAdapters.ContractToViewAdapter(contract);
// this 在这里是 MainWindow 或者 MainPage,或者其它任何能够承载 FrameworkElement 的对象。
this.Content = element;

以上的这两端代码都可以写在 MainWindow 的 Loaded 事件中。

对 MAF 吐一下槽

MAF 框架对插件和宿主程序集所在的文件夹结构有要求。这可是非常讨厌的一项特性!因为当我们希望采用 MAF 框架的时候,我们的应用程序可能已经有自己独特的一套目录了。就算我们从零开始写应用,采用 MAF 约定的方式组织 dll 也是很丑的方式(带有很重的 MAF 的影子)。

它没有提供任何的配置,而且如果不按照约定放置文件夹,还会发生如下错误:


参考资料

WPF 跨应用程序域的 UI(Cross AppDomain UI)的更多相关文章

  1. 跨应用程序域(AppDomain)的单例(Singleton)实现

    转载自: 跨应用程序域(AppDomain)的单例(Singleton)实现 - CorePlex代码库 - CorePlex官方网站,Visual Studio插件,代码大全,代码仓库,代码整理,分 ...

  2. WPF 同一窗口内的多线程/多进程 UI(使用 SetParent 嵌入另一个窗口)

    原文 WPF 同一窗口内的多线程/多进程 UI(使用 SetParent 嵌入另一个窗口) WPF 的 UI 逻辑只在同一个线程中,这是学习 WPF 开发中大家几乎都会学习到的经验.如果希望做不同线程 ...

  3. 解析.NET对象的跨应用程序域访问--AppDomain(上篇)

    在目前的项目开发中,分布式开发已经逐渐成为主流.一个项目要是没有采用分布式架构,都不好意思跟别人说这是一个完整的项目.这句话虽然有些过激,但是随着人们对效率的要求在提高,以及产品需要提升用户体验.只有 ...

  4. 如何跨线程访问Winform中的UI元素

    如何跨线程访问Winform中的UI元素 假如制作一个Socket聊天应用程序,很可能会用到多线程: 例如为Receive方法开辟单独一个线程,例如为Receive方法开辟单独一个线程(后台运行的线程 ...

  5. 【.net 深呼吸】跨应用程序域执行程序集

    应用程序域,你在网上可以查到它的定义,凡是概念性的东西,大伙儿只需要会搜索就行,内容看了就罢,不用去记忆,更不用去背,“名词解释”是大学考试里面最无聊最没水平的题型. 简单地说,应用程序域让你可以在一 ...

  6. 面向UI编程:ui.js 1.0 粗糙版本发布,分布式开发+容器化+组件化+配置化框架,从无到有的艰难创造

    时隔第一次被UI思路激励,到现在1.0的粗糙版本发布,掐指一算整整半年了.半年之间,有些细节不断推翻重做,再推翻再重做.时隔今日,终于能先出来个东西了,这个版本很粗糙,主体功能大概能实现了,但是还是有 ...

  7. 解析.NET对象的跨应用程序域访问(下篇)

    转眼就到了元宵节,匆匆忙忙的脚步是我们在为生活奋斗的写照,新的一年,我们应该努力让自己有不一样的生活和追求.生命不息,奋斗不止.在上篇博文中主要介绍了.NET的AppDomain的相关信息,在本篇博文 ...

  8. 解析.NET对象的跨应用程序域访问(上篇)

    在目前的项目开发中,分布式开发已经逐渐成为主流.一个项目要是没有采用分布式架构,都不好意思跟别人说这是一个完整的项目.这句话虽然有些过激,但是随着人们对效率的要求在提高,以及产品需要提升用户体验.只有 ...

  9. NET对象的跨应用程序域

    NET对象的跨应用程序域 转眼就到了元宵节,匆匆忙忙的脚步是我们在为生活奋斗的写照,新的一年,我们应该努力让自己有不一样的生活和追求.生命不息,奋斗不止.在上篇博文中主要介绍了.NET的AppDoma ...

随机推荐

  1. Eclipse-环境搭建(缅怀篇)

    JDK 下载jdk安装并配置环境变量运行java -version查看是否安装配置成功 Eclipse 下载eclipse,直接解压到目录 eclipse配置jre 设置complie编译等级 Ecl ...

  2. 009——数组(九) each list array_map array_walk array_walk_recursive

    <?php /** * 9 数组 each list array_map array_walk array_walk_recursive */ //each() 返回数组中的键名和键值生成新数组 ...

  3. C#笔记 -- 协变、逆变

    协变 理解:在泛型和委托中, 让使用某个泛型参数A的类型可以用一个使用由A派生的泛型参数B的类型实例化,(小=> 大)如 ​ // IEnumerable<Animal> 与 Lis ...

  4. LINUX中文件描述符传递

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

  5. C++面向对象高级编程(四)基础篇

    技术在于交流.沟通,转载请注明出处并保持作品的完整性. 一.Static 二.模板类和模板函数 三.namespace 一.Static 静态成员是“类级别”的,也就是它和类的地位等同,而普通成员是“ ...

  6. InfluxDB使用纪录

    我是Mac环境 1.安装 brew install influxdb 安装完成后,默认目录为/usr/local/opt/influxdb. 2.安装完成后,打开influxdb服务. $ influ ...

  7. VS2010上写QT代码,但是显示不出来QString的值-解决办法

    我的配置是vs2010和qt,debug下看不到 QString的值 根据 http://www.cnblogs.com/russinovich/archive/2012/06/29/2569898. ...

  8. v-if和v-show小对比

    相同点 都可以控制元素的显示与不显示.在判断DOM节点是否要显示. 不同点 1.实现方式 v-if是根据后面的数据的真假判断直接从DOM树上删除或重建元素节点. v-show 只是修改元素的css的样 ...

  9. Python中方法的缺省参数问题分析

    引言: 在Python中可以缺省给方法制定缺省值,但是这个缺省值在某些情况下确是和我们预期不太一致的-... 这个诡异的问题,曾经困然了我几天时间,才最终定位出来-.. 测试代码 from datet ...

  10. 关于Fildder更改ip简单配置

    之前由于我们公司之前的域名备案 所以临时购买了一个域名主机,可能你如果不配置的话有时候看不到你自己app一些抓包信息具体分为以下几步 配置Filter过滤器记得勾选 第一次进入的时候 2.然后我们再H ...