JointCode.Shuttle 是一个用于进程内 AppDomain 间通讯的服务架构(不支持跨进程),它旨在取代运行时库提供的 MarshalByrefObject 的功能。git
本文主要介绍如何经过 JointCode.Shuttle 访问任意 AppDomain 的服务。github
当咱们要进行跨 AppDomain 调用时,通常咱们会让须要跨 AppDomain 操做的类(服务类)继承自 MarshalByrefObject,接着在调用 AppDomain(父 AppDomain)中建立目标 AppDomain(子 AppDomain),而后直接经过子 AppDomain 的引用建立所需的服务对象,并调用服务对象的相关方法。代码就像这样:架构
1 namespace JoitCode.Shuttle.SimpleSample 2 { 3 public class MyService : MarshalByRefObject 4 { 5 public void Do() { } 6 } 7 8 class Program 9 { 10 static void Main(string[] args) 11 { 12 // 在默认 AppDomain 中建立一个子 AppDomain 13 var serviceDomain = AppDomain.CreateDomain("ServiceDomain", null, null); 14 15 var myService = (MyService)serviceDomain.CreateInstanceAndUnwrap 16 (typeof(MyService).Assembly.FullName, 17 "JoitCode.Shuttle.SimpleSample.MyService"); 18 19 myService.Do(); 20 21 Console.Read(); 22 } 23 } 24 }
显然,经过这种方式,咱们没有办法直接从子 AppDomain 中访问父 AppDomain。固然,咱们也能够经过一些变通办法来实现双向通讯,好比像下面这样:ui
public class MarshalByRefCrossAccess1 : MarshalByRefObject { public void Run() { Console.Write("Now, we are running in AppDomain [{0}]!", AppDomain.CurrentDomain.FriendlyName); Console.WriteLine(); } } public class MarshalByRefCrossAccess2 : MarshalByRefObject { public void Run(MarshalByRefCrossAccess1 arg) { Console.WriteLine("Currently, we are running in AppDomain [{0}]: ", AppDomain.CurrentDomain.FriendlyName); arg.Run(); } } class Program { static void Main(string[] args) { var remoteDomain = AppDomain.CreateDomain(Guid.NewGuid().ToString(), null, null); var access2 = (MarshalByRefCrossAccess2)remoteDomain.CreateInstanceAndUnwrap (typeof(MarshalByRefCrossAccess2).Assembly.FullName, typeof(MarshalByRefCrossAccess2).FullName); var access1 = new MarshalByRefCrossAccess1(); access2.Run(access1); Console.Read(); } }
尽管能够变通实现双向通讯,但诸如此类的办法老是显得不那么天然。更为重要的是,这是双向通讯,通讯双方互相持有对方,所以咱们能够这样达到目的。spa
但若是咱们想要与之通讯的对象根本不在咱们掌控之中(即不持有其引用)呢?code
好比说,咱们在一个 AppDomain A 中建立了另外两个 AppDomain B 和 C,如今若是 AppDomain B 要访问 AppDomain C,又当如何呢?对象
JointCode.Shuttle 天生就可以解决这种问题。blog
咱们为此写了一个示例。如下是该示例输出的部分截图:继承
若是您对示例源码感兴趣,请移步前往 此处 下载(示例名称:ShuttleDomain任意域访问)。进程