使用 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     }
View Code

接着编写一个实现该契约的服务类,并对其应用 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     }
View Code

由于要实现跨 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     }
View Code

现在,可以开始使用 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) 进行跨字段验证

使用 JSR 303 在 JSF 中使用内联消息进行跨字段验证

使用服务帐户进行跨项目管理