使用 JointCode.Shuttle 进行跨 AppDomain 通信的一个简单示例
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用 JointCode.Shuttle 进行跨 AppDomain 通信的一个简单示例相关的知识,希望对你有一定的参考价值。
JointCode.Shuttle 是一个用于进程内 AppDomain 间通信的服务架构(不支持跨进程)。
本文通过一个简单的示例来演示如何使用 JointCode.Shuttle。
JointCode.Shuttle 的发行包
在 JointCode.Shuttle 的发行包中,包含两个文件:JointCode.Shuttle.dll 和 JointCode.Shuttle.Library.dll,其中 JointCode.Shuttle.dll 是使用托管语言编写的库文件,JointCode.Shuttle.Library.dll 则是前者依赖的、使用非托管语言编写的一个组件。
准备工作
要使用 JointCode.Shuttle,我们首先需要在项目中引用 JointCode.Shuttle.dll 这个程序集,同时要把 JointCode.Shuttle.Library.dll 复制到项目编译之后 JointCode.Shuttle.dll 所在的文件夹中(例如,假设项目编译后,JointCode.Shuttle.dll 被复制到 c:/projects/sampleproject 文件夹中,则需要手动将 JointCode.Shuttle.Library.dll 复制到此文件夹)。
开始编码
JointCode.Shuttle 是面向接口编程的,所以我们首先需要编写一个服务接口(也叫服务契约),并对其应用 ServiceInterface 属性。
1 [ServiceInterface] 2 public interface ISimpleService 3 { 4 string GetOutput(string input); 5 }
接着编写一个实现该契约的服务类,并对其应用 ServiceClass 属性。
1 [ServiceClass(typeof(ISimpleService), Lifetime = LifetimeEnum.Transient)] 2 public class SimpleService : ISimpleService 3 { 4 public string GetOutput(string input) 5 { 6 return string.Format 7 ("SimpleService.GetOutput says: now, we are running in AppDomain: {0}, and the input passed from the caller is: {1}", 8 AppDomain.CurrentDomain.FriendlyName, input); 9 } 10 }
由于要实现跨 AppDomain 通信,因此这里我们需要编写一个用于启动远程服务的类,并让该类继承自 MarshalByRefObject。
1 public class ServiceProvider : MarshalByRefObject 2 { 3 // 这里必须使用一个字段来持有 ShuttleDomain 实例的引用,因为如果该实例被垃圾回收, 4 // 那么通过该实例注册的所有服务也会被注销 5 ShuttleDomain _shuttleDomain; 6 7 public void RegisterServices() 8 { 9 // 注册服务组时,需要传递一个 Guid 对象 10 var guid = new Guid(); 11 _shuttleDomain.RegisterServiceGroup(ref guid, 12 new ServiceTypePair(typeof(ISimpleService), typeof(SimpleService))); 13 } 14 15 public void CreateShuttleDomain() 16 { 17 // 创建一个 ShuttleDomain 18 _shuttleDomain = ShuttleDomainHelper.Create("domain1", "domain1"); 19 } 20 21 public void DisposeShuttleDomain() 22 { 23 _shuttleDomain.Dispose(); 24 } 25 }
现在,可以开始使用 JointCode.Shuttle 了。有关使用方法,可以参见注释,代码如下:
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 // 要使用 JointCode.Shuttle,首先必须初始化 ShuttleDomain。 6 // 这个初始化操作一般在默认 AppDomain 执行,但也可以在其他 AppDomain 中执行,都是一样的。 7 ShuttleDomain.Initialize(); 8 9 // 在默认 AppDomain 中创建一个子 AppDomain,并在该 AppDomain 中创建一个 ServiceProvider 对象。 10 var serviceEnd1Domain = AppDomain.CreateDomain("ServiceEndDomain1", null, null); 11 var serviceProvider = (ServiceProvider)serviceEnd1Domain.CreateInstanceAndUnwrap 12 (typeof(Program).Assembly.FullName, "JoitCode.Shuttle.SimpleSample.ServiceProvider"); 13 14 // 在子 AppDomain 中,创建一个 ShuttleDomain 实例。 15 serviceProvider.CreateShuttleDomain(); 16 17 // 在子 AppDomain 中,注册 ISimpleService 服务。 18 serviceProvider.RegisterServices(); 19 20 // 在默认 AppDomain 中,创建一个 ShuttleDomain。 21 // 事实上,在应用程序的每个 AppDomain 中都需要有一个 ShuttleDomain 对象。 22 // 该对象用于与其他 AppDomain 中的 ShuttleDomain 对象通信。 23 var str = Guid.NewGuid().ToString(); 24 var shuttleDomain = ShuttleDomainHelper.Create(str, str); 25 26 // 在默认 AppDomain 中,获取子 AppDomain 中注册的服务实例。 27 // 目前服务实例的默认生存期为 1 分钟。每次调用服务方法时,服务实例的生存期延长 30 秒。 28 ISimpleService service; 29 if (shuttleDomain.TryGetService(out service)) 30 { 31 try 32 { 33 Console.WriteLine("Currently, we are running in AppDomain {0} before calling the remote service method...", 34 AppDomain.CurrentDomain.FriendlyName); 35 36 Console.WriteLine(); 37 // 调用子 AppDomain 中注册的 ISimpleService 服务实例的服务方法。 38 var output = service.GetOutput("China"); 39 Console.WriteLine(output); 40 41 Console.WriteLine(); 42 Console.WriteLine("Tests completed..."); 43 } 44 catch 45 { 46 Console.WriteLine(); 47 Console.WriteLine("Failed to invoke the remote service method..."); 48 } 49 } 50 else 51 { 52 Console.WriteLine(); 53 Console.WriteLine("Failed to create remote service instance..."); 54 } 55 56 // 立即释放子 AppDomain 中生成的 ISimpleService 服务实例,而不用等待其生存期结束。 57 // 此为可选操作,因为即使不手动释放 ISimpleService 服务实例,在其生命期结束之时系统也会自动释放该实例 58 //(如果 ISimpleService 实现了 IDisposable,还会调用其 Dispose 方法) 59 shuttleDomain.ReleaseService(service); 60 61 // 在子 AppDomain 中,释放缓存的 ShuttleDomain 实例。这将会注销通过该实例注册的所有服务(在本示例中,即 ISimpleService 服务)。 62 serviceProvider.DisposeShuttleDomain(); 63 64 Console.Read(); 65 } 66 }
如需完整代码,请点击 此处 下载。
以上是关于使用 JointCode.Shuttle 进行跨 AppDomain 通信的一个简单示例的主要内容,如果未能解决你的问题,请参考以下文章
使用 JointCode.Shuttle 管理远程服务对象的生命期
使用 JointCode.Shuttle 动态注册 / 注销服务
JointCode.Shuttle,一个简单高效的跨 AppDomain 通信的服务框架
使用 Hibernate Validator (JSR 303) 进行跨字段验证