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

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

对 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. php 模拟 asp.net webFrom 按钮提交事件

    由于公司需要php方面的项目开发,php刚刚入门,在写按钮提交过程中,asp.net里的按钮事件更好些.先看下面的代码, <? require_once '../inc/EventHelper. ...

  2. Android 数据库 ObjectBox 源码解析

    一.ObjectBox 是什么? greenrobot 团队(现有 EventBus.greenDAO 等开源产品)推出的又一数据库开源产品,主打移动设备.支持跨平台,最大的优点是速度快.操作简洁,目 ...

  3. jquery.chosen.js下拉选择框美化插件项目实例

    由于之前使用的bootstrap-select插件是建立在bootstrap基础上的,实际使用到项目中的时候,与我们使用的ace-admin(基于bootstrap)存在样式冲突,导致下拉框的样式发生 ...

  4. [Vue]webpack的require与require.context

    1.require 1.1完整路径的require语句: require('tools'); //preset alias tools require('./js/main'); 1.2带表达式的 r ...

  5. pahlcon:cookies设置

    非加密方式(简单,但不推荐) 步骤 1 在全局容器中加入Cookie: $di->set('cookies', function () { $cookies = new \Phalcon\Htt ...

  6. VS2013 The Debugger Resource DLL is out of date

    折磨了我一天的问题,亲们,记住,下载vs2013 update5 ,别的方法不用试了,完全没用!

  7. 微信小程序------基本组件

    今天主要是简单的讲一下小程序当中的一些组件,微信文档上也是有的.但我还是坚持写一下,因为写博客可以再一次得到提高,印象更深刻,虽然很简单,但贵在坚持. 先来看看效果图: 1:进度条(progress) ...

  8. HDU5137-最短路-删点

    How Many Maos Does the Guanxi Worth Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 512000/5 ...

  9. 搭建多master的saltstack环境

    0.16.0版本的发布,带来了minion可以连接多Master的特性. 这种方式称为多master( multi-master )配置, 使环境中的SaltStack冗余.在这种配置下,Salt M ...

  10. 【Python】高阶函数介绍

    其实函数可以作为变量,之前学过C++,对于这种用法并不奇怪.无非就是函数充当变量,可以传入函数而已. 下面分别介绍 Python 中常见的高阶函数:map/reduce, filter, sorted ...