C# での Reliable Services を使用したサービスのリモート処理Service remoting in C# with Reliable Services

Web API や Windows Communication Foundation など、特定の通信プロトコルやスタックにひも付けされていないサービスでは、サービスのリモート プロシージャ コールを迅速かつ簡単に設定するリモート処理呼び出しを、Reliable Services フレームワークが提供します。For services that aren't tied to a particular communication protocol or stack, such as a web API, Windows Communication Foundation, or others, the Reliable Services framework provides a remoting mechanism to quickly and easily set up remote procedure calls for services. この記事では、C# で作成されたサービス向けにリモート プロシージャ コールを設定する方法について説明します。This article discusses how to set up remote procedure calls for services written with C#.

サービスでのリモート処理の設定Set up remoting on a service

サービスのリモート処理は、次の 2 つの簡単な手順で設定できます。You can set up remoting for a service in two simple steps:

  1. 実装するサービスのインターフェイスを作成します。Create an interface for your service to implement. このインターフェイスは、サービスのリモート プロシージャ コールで使用できるメソッドを定義します。This interface defines the methods that are available for a remote procedure call on your service. このメソッドはタスクを返す非同期メソッドである必要があります。The methods must be task-returning asynchronous methods. インターフェイスは Microsoft.ServiceFabric.Services.Remoting.IService を実装し、そのサービスにリモート処理インターフェイスがあることを示す必要があります。The interface must implement Microsoft.ServiceFabric.Services.Remoting.IService to signal that the service has a remoting interface.
  2. サービスでリモート処理リスナーを使用します。Use a remoting listener in your service. リモート処理リスナーは、リモート処理機能を提供する ICommunicationListener の実装です。A remoting listener is an ICommunicationListener implementation that provides remoting capabilities. Microsoft.ServiceFabric.Services.Remoting.Runtime 名前空間には、ステートレス サービスとステートフル サービスの拡張メソッド CreateServiceRemotingInstanceListeners が含まれています。このメソッドは、既定のリモート処理トランスポート プロトコルを使用してリモート処理リスナーを作成するために使用できます。The Microsoft.ServiceFabric.Services.Remoting.Runtime namespace contains the extension method CreateServiceRemotingInstanceListeners for both stateless and stateful services that can be used to create a remoting listener by using the default remoting transport protocol.

注意

Remoting 名前空間は、Microsoft.ServiceFabric.Services.Remoting という別の NuGet パッケージとして提供されています。The Remoting namespace is available as a separate NuGet package called Microsoft.ServiceFabric.Services.Remoting.

たとえば、次のステートレス サービスでは、リモート プロシージャ コールで "Hello World" を取得する 1 つのメソッドを公開します。For example, the following stateless service exposes a single method to get "Hello World" over a remote procedure call.

using Microsoft.ServiceFabric.Services.Communication.Runtime;
using Microsoft.ServiceFabric.Services.Remoting;
using Microsoft.ServiceFabric.Services.Remoting.Runtime;
using Microsoft.ServiceFabric.Services.Runtime;

public interface IMyService : IService
{
    Task<string> HelloWorldAsync();
}

class MyService : StatelessService, IMyService
{
    public MyService(StatelessServiceContext context)
        : base (context)
    {
    }

    public Task<string> HelloWorldAsync()
    {
        return Task.FromResult("Hello!");
    }

    protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
    {
     return this.CreateServiceRemotingInstanceListeners();
    }
}

注意

サービス インターフェイスの引数と戻り値の型は、単純型、複合型、またはカスタム型のいずれかにできますが、.NET の DataContractSerializer によってシリアル化できる必要があります。The arguments and the return types in the service interface can be any simple, complex, or custom types, but they must be able to be serialized by the .NET DataContractSerializer.

リモート サービス メソッドの呼び出しCall remote service methods

リモート処理スタックを使用したサービスでのメソッドの呼び出しは、 Microsoft.ServiceFabric.Services.Remoting.Client.ServiceProxy クラスによるサービスへのローカル プロキシを使用して実行されます。Calling methods on a service by using the remoting stack is done by using a local proxy to the service through the Microsoft.ServiceFabric.Services.Remoting.Client.ServiceProxy class. ServiceProxy メソッドは、サービスに実装されている同じインターフェイスを使用してローカル プロキシを作成します。The ServiceProxy method creates a local proxy by using the same interface that the service implements. そのプロキシを使用して、インターフェイス上のメソッドをリモートで呼び出すことができます。With that proxy, you can call methods on the interface remotely.


IMyService helloWorldClient = ServiceProxy.Create<IMyService>(new Uri("fabric:/MyApplication/MyHelloWorldService"));

string message = await helloWorldClient.HelloWorldAsync();

リモート処理フレームワークは、サービスでスローされた例外をクライアントに伝達します。The remoting framework propagates exceptions thrown by the service to the client. 結果として、ServiceProxy が使用される場合はクライアントが、サービスによってスローされる例外を処理する必要があります。As a result, when ServiceProxyis used, the client is responsible for handling the exceptions thrown by the service.

サービス プロキシの有効期間Service proxy lifetime

サービス プロキシの作成は負荷の軽い処理であり、必要だけいくつでも作成できます。Service proxy creation is a lightweight operation, so you can create as many as you need. サービス プロキシ インスタンスは、それらが必要とされる限り再利用することができます。Service proxy instances can be reused for as long as they are needed. リモート プロシージャ コールから例外がスローされても、同じプロキシ インスタンスを再利用できます。If a remote procedure call throws an exception, you can still reuse the same proxy instance. 各サービス プロキシは、メッセージをネットワーク経由で送信するための通信クライアントを含んでいます。Each service proxy contains a communication client used to send messages over the wire. リモート呼び出しが実行されると、通信クライアントが有効かどうかを調べる内部チェックが実行されます。While invoking remote calls, internal checks are performed to determine if the communication client is valid. それらのチェックの結果に基づいて、必要な場合は通信クライアントが再作成されます。Based on the results of those checks, the communication client is re-created if needed. したがって、例外が発生した場合に、ユーザーが ServiceProxy を再作成する必要はありません。Therefore, if an exception occurs, you do not need to re-create ServiceProxy.

サービス プロキシ ファクトリの有効期間Service proxy factory lifetime

ServiceProxyFactory は、さまざまなリモート処理インターフェイスのプロキシ インスタンスを作成するファクトリです。ServiceProxyFactory is a factory that creates proxy instances for different remoting interfaces. API ServiceProxyFactory.CreateServiceProxy を使用してプロキシを作成する場合、フレームワークによってシングルトン サービス プロキシが作成されます。If you use the API ServiceProxyFactory.CreateServiceProxy to create a proxy, the framework creates a singleton service proxy. 手動での作成は、IServiceRemotingClientFactory プロパティをオーバーライドする必要があるときに効果的です。It is useful to create one manually when you need to override IServiceRemotingClientFactory properties. ファクトリの作成は負荷の高い操作です。Factory creation is an expensive operation. サービス プロキシ ファクトリは、通信クライアントの内部キャッシュを管理します。A service proxy factory maintains an internal cache of the communication client. サービス プロキシ ファクトリは、できるだけ長くキャッシュすることがベスト プラクティスです。A best practice is to cache the service proxy factory for as long as possible.

リモート処理の例外処理Remoting exception handling

サービス API によってスローされるリモート処理の例外はすべて、AggregateException としてクライアントに返されます。All remote exceptions thrown by the service API are sent back to the client as AggregateException. リモート処理の例外は、DataContract によってシリアル化できる必要があります。Remote exceptions should be able to be serialized by DataContract. そうでない場合、プロキシ API はその内部のシリアル化エラーによって ServiceException をスローします。If they are not, the proxy API throws ServiceException with the serialization error in it.

サービス プロキシは、それが作成されたサービス パーティションのすべてのフェールオーバー例外を処理します。The service proxy handles all failover exceptions for the service partition it is created for. フェールオーバー例外 (一時的ではない例外) が発生した場合、エンドポイントを再度解決し、正しいエンドポイントでの呼び出しを再試行します。It re-resolves the endpoints if there are failover exceptions (non-transient exceptions) and retries the call with the correct endpoint. フェールオーバー例外の再試行回数に上限はありません。The number of retries for failover exceptions is indefinite. 一時的な例外が発生した場合、プロキシは呼び出しを再試行します。If transient exceptions occur, the proxy retries the call.

既定の再試行パラメーターは、OperationRetrySettings で指定します。Default retry parameters are provided by OperationRetrySettings.

ユーザーは、ServiceProxyFactory コンストラクターに OperationRetrySettings オブジェクトを渡すことによって、これらの値を構成できます。A user can configure these values by passing the OperationRetrySettings object to the ServiceProxyFactory constructor.

リモート処理 V2 スタックを使用するUse the remoting V2 stack

NuGet リモート処理パッケージのバージョン 2.8 より、リモート処理 V2 スタックを使用するオプションが用意されています。As of version 2.8 of the NuGet remoting package, you have the option to use the remoting V2 stack. リモート処理 V2 スタックはパフォーマンスが向上しています。The remoting V2 stack performs better. カスタムのシリアル化や、プラグ可能な範囲が広がった API などの機能も提供されます。It also provides features like custom serialization and more pluggable APIs. テンプレート コードでは、引き続きリモート処理 V1 スタックが使用されます。Template code continues to use the remoting V1 stack. リモート処理 V2 は V1 (前のリモート処理スタック) と互換性がありません。Remoting V2 is not compatible with V1 (the previous remoting stack). V1 から V2 へのアップグレードに関する記事の手順に従って、サービスの可用性への影響を回避します。Follow the instructions in the article Upgrade from V1 to V2 to avoid effects on service availability.

V2 スタックを有効にするには、次の方法を使用できます。The following approaches are available to enable the V2 stack.

アセンブリ属性を利用して V2 スタックを使用するUse an assembly attribute to use the V2 stack

これらの手順では、V2 スタックを使用するために、アセンブリ属性を使ってテンプレート コードを変更します。These steps change the template code to use the V2 stack by using an assembly attribute.

  1. サービス マニフェストで、エンドポイント リソースを "ServiceEndpoint" から "ServiceEndpointV2" に変更します。Change the endpoint resource from "ServiceEndpoint" to "ServiceEndpointV2" in the service manifest.

    <Resources>
     <Endpoints>
       <Endpoint Name="ServiceEndpointV2" />
     </Endpoints>
    </Resources>
    
  2. Microsoft.ServiceFabric.Services.Remoting.Runtime.CreateServiceRemotingInstanceListeners 拡張メソッドを使用して、リモート処理リスナーを作成します (V1 と V2 の両方で同一)。Use the Microsoft.ServiceFabric.Services.Remoting.Runtime.CreateServiceRemotingInstanceListeners extension method to create remoting listeners (equal for both V1 and V2).

     protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
     {
         return this.CreateServiceRemotingInstanceListeners();
     }
    
  3. リモート処理インターフェイスが含まれているアセンブリに、FabricTransportServiceRemotingProvider 属性を指定してマークを付けます。Mark the assembly that contains the remoting interfaces with a FabricTransportServiceRemotingProvider attribute.

    [assembly: FabricTransportServiceRemotingProvider(RemotingListenerVersion = RemotingListenerVersion.V2, RemotingClientVersion = RemotingClientVersion.V2)]
    

クライアント プロジェクトでは、コードの変更は必要ありません。No code changes are required in the client project. 上に示したアセンブリ属性が確実に使用されるように、目的のインターフェイス アセンブリを使用してクライアント アセンブリをビルドします。Build the client assembly with the interface assembly to make sure that the assembly attribute previously shown is used.

明示的な V2 クラスを利用して V2 スタックを使用するUse explicit V2 classes to use the V2 stack

アセンブリ属性を使用する代わりに、明示的な V2 クラスを使用して V2 スタックを有効にすることもできます。As an alternative to using an assembly attribute, the V2 stack also can be enabled by using explicit V2 classes.

これらの手順では、V2 スタックを使用するために、明示的な V2 クラスを使ってテンプレート コードを変更します。These steps change the template code to use the V2 stack by using explicit V2 classes.

  1. サービス マニフェストで、エンドポイント リソースを "ServiceEndpoint" から "ServiceEndpointV2" に変更します。Change the endpoint resource from "ServiceEndpoint" to "ServiceEndpointV2" in the service manifest.

    <Resources>
     <Endpoints>
       <Endpoint Name="ServiceEndpointV2" />
     </Endpoints>
    </Resources>
    
  2. Microsoft.ServiceFabric.Services.Remoting.V2.FabricTransport.Runtime 名前空間の FabricTransportServiceRemotingListener を使用します。Use FabricTransportServiceRemotingListener from the Microsoft.ServiceFabric.Services.Remoting.V2.FabricTransport.Runtime namespace.

    protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
     {
         return new[]
         {
             new ServiceInstanceListener((c) =>
             {
                 return new FabricTransportServiceRemotingListener(c, this);
    
             })
         };
     }
    
  3. Microsoft.ServiceFabric.Services.Remoting.V2.FabricTransport.Client 名前空間の FabricTransportServiceRemotingClientFactory を使用してクライアントを作成します。Use FabricTransportServiceRemotingClientFactory from the Microsoft.ServiceFabric.Services.Remoting.V2.FabricTransport.Client namespace to create clients.

    var proxyFactory = new ServiceProxyFactory((c) =>
           {
               return new FabricTransportServiceRemotingClientFactory();
           });
    

リモート処理 V1 からリモート処理 V2 にアップグレードするUpgrade from remoting V1 to remoting V2

V1 から V2 にアップグレードするには、2 段階のアップグレードが必要です。To upgrade from V1 to V2, two-step upgrades are required. この順序で以下の手順に従います。Follow the steps in this sequence.

  1. 次の属性を使用して、V1 サービスを V2 サービスにアップグレードします。Upgrade the V1 service to V2 service by using this attribute. この変更によって、サービスが V1 および V2 リスナーでリッスンするようにします。This change makes sure that the service listens on the V1 and V2 listener.

    a.a. サービス マニフェストに、"ServiceEndpointV2" という名前のエンドポイント リソースを追加します。Add an endpoint resource with the name "ServiceEndpointV2" in the service manifest.

    <Resources>
      <Endpoints>
        <Endpoint Name="ServiceEndpointV2" />  
      </Endpoints>
    </Resources>
    

    b.b. 次の拡張メソッドを使用して、リモート処理リスナーを作成します。Use the following extension method to create a remoting listener.

    protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
    {
        return this.CreateServiceRemotingInstanceListeners();
    }
    

    c.c. リモート処理インターフェイスで、V1 および V2 リスナーと V2 クライアントを使用するためのアセンブリ属性を追加します。Add an assembly attribute on remoting interfaces to use the V1 and V2 listener and the V2 client.

    [assembly: FabricTransportServiceRemotingProvider(RemotingListenerVersion = RemotingListenerVersion.V2|RemotingListenerVersion.V1, RemotingClientVersion = RemotingClientVersion.V2)]
    
    
  2. V2 クライアントの属性を使用して、V1 クライアントを V2 クライアントにアップグレードします。Upgrade the V1 client to a V2 client by using the V2 client attribute. このステップによって、クライアントが V2 スタックを使用するようにします。This step makes sure the client uses the V2 stack. クライアント プロジェクトやサービスでの変更は必要ありません。No change in the client project/service is required. 更新したインターフェイス アセンブリを使用してクライアント プロジェクトをビルドすれば十分です。Building client projects with updated interface assembly is sufficient.

  3. この手順は省略可能です。This step is optional. V2 リスナー属性を使用して、V2 サービスをアップグレードします。Use the V2 listener attribute, and then upgrade the V2 service. この手順によって、サービスが V2 リスナーでのみリッスンするようにします。This step makes sure that the service is listening only on the V2 listener.

    [assembly: FabricTransportServiceRemotingProvider(RemotingListenerVersion = RemotingListenerVersion.V2, RemotingClientVersion = RemotingClientVersion.V2)]
    

リモート処理 V2 (インターフェイス互換) スタックを使用するUse the remoting V2 (interface compatible) stack

リモート処理 V2 (インターフェイス互換、V2_1 と呼ばれます) スタックは、V2 リモート処理スタックのすべての機能を備えています。The remoting V2 (interface compatible, known as V2_1) stack has all the features of the V2 remoting stack. そのインターフェイス スタックは、リモート処理 V1 スタックと互換性がありますが、V2 および V1 との下位互換性はありません。Its interface stack is compatible with the remoting V1 stack, but it is not backward compatible with V2 and V1. サービスの可用性に影響を与えずに V1 から V2_1 にアップグレードするには、V1 から V2 (インターフェイス互換) へのアップグレードに関する記事の手順に従ってください。To upgrade from V1 to V2_1 without affecting service availability, follow the steps in the article Upgrade from V1 to V2 (interface compatible).

アセンブリ属性を利用してリモート処理 V2 (インターフェイス互換) スタックを使用するUse an assembly attribute to use the remoting V2 (interface compatible) stack

以下の手順に従って V2_1 スタックに変更します。Follow these steps to change to a V2_1 stack.

  1. サービス マニフェストに、"ServiceEndpointV2_1" という名前のエンドポイント リソースを追加します。Add an endpoint resource with the name "ServiceEndpointV2_1" in the service manifest.

    <Resources>
     <Endpoints>
       <Endpoint Name="ServiceEndpointV2_1" />  
     </Endpoints>
    </Resources>
    
  2. リモート処理拡張メソッドを使用して、リモート処理リスナーを作成します。Use the remoting extension method to create a remoting listener.

     protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
     {
         return this.CreateServiceRemotingInstanceListeners();
     }
    
  3. リモート処理インターフェイスにアセンブリ属性を追加します。Add an assembly attribute on remoting interfaces.

     [assembly:  FabricTransportServiceRemotingProvider(RemotingListenerVersion=  RemotingListenerVersion.V2_1, RemotingClientVersion= RemotingClientVersion.V2_1)]
    
    

クライアント プロジェクトでは、変更は必要ありません。No changes are required in the client project. 前記のアセンブリ属性が確実に使用されるように、目的のインターフェイス アセンブリを使用してクライアント アセンブリをビルドします。Build the client assembly with the interface assembly to make sure that the previous assembly attribute is being used.

明示的リモート処理クラスを使用して V2 (インターフェイス互換) バージョンのリスナー/クライアント ファクトリを作成するUse explicit remoting classes to create a listener/client factory for the V2 (interface compatible) version

次の手順に従います。Follow these steps:

  1. サービス マニフェストに、"ServiceEndpointV2_1" という名前のエンドポイント リソースを追加します。Add an endpoint resource with the name "ServiceEndpointV2_1" in the service manifest.

    <Resources>
     <Endpoints>
       <Endpoint Name="ServiceEndpointV2_1" />  
     </Endpoints>
    </Resources>
    
  2. リモート処理 V2 リスナーを使用しますUse the remoting V2 listener. 使用される既定のサービス エンドポイント リソース名は、"ServiceEndpointV2_1" です。The default service endpoint resource name used is "ServiceEndpointV2_1." これはサービス マニフェストで定義されている必要があります。It must be defined in the service manifest.

    protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
     {
         return new[]
         {
             new ServiceInstanceListener((c) =>
             {
                 var settings = new FabricTransportRemotingListenerSettings();
                 settings.UseWrappedMessage = true;
                 return new FabricTransportServiceRemotingListener(c, this,settings);
    
             })
         };
     }
    
  3. V2 クライアント ファクトリを使用します。Use the V2 client factory.

    var proxyFactory = new ServiceProxyFactory((c) =>
           {
             var settings = new FabricTransportRemotingSettings();
             settings.UseWrappedMessage = true;
             return new FabricTransportServiceRemotingClientFactory(settings);
           });
    

リモート処理 V1 からリモート処理 V2 (インターフェイス互換) にアップグレードするUpgrade from remoting V1 to remoting V2 (interface compatible)

V1 から V2 (インターフェイス互換、V2_1 と呼ばれます) にアップグレードするには、2 段階のアップグレードが必要です。To upgrade from V1 to V2 (interface compatible, known as V2_1), two-step upgrades are required. この順序で以下の手順に従います。Follow the steps in this sequence.

注意

V1 から V2 にアップグレードする場合は、V2 を使用するように Remoting 名前空間が更新されていることを確認します。When upgrading from V1 to V2, ensure the Remoting namespace is updated to use V2. 例:'Microsoft.ServiceFabric.Services.Remoting.V2.FabricTransport.Client`Example: 'Microsoft.ServiceFabric.Services.Remoting.V2.FabricTransport.Client`

  1. 次の属性を使用して、V1 サービスを V2_1 サービスにアップグレードします。Upgrade the V1 service to V2_1 service by using the following attribute. この変更によって、サービスは V1 および V2_1 リスナーでリッスンするようになります。This change makes sure that the service is listening on the V1 and the V2_1 listener.

    a.a. サービス マニフェストに、"ServiceEndpointV2_1" という名前のエンドポイント リソースを追加します。Add an endpoint resource with the name "ServiceEndpointV2_1" in the service manifest.

    <Resources>
      <Endpoints>
        <Endpoint Name="ServiceEndpointV2_1" />  
      </Endpoints>
    </Resources>
    

    b.b. 次の拡張メソッドを使用して、リモート処理リスナーを作成します。Use the following extension method to create a remoting listener.

    protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
    {
        return this.CreateServiceRemotingInstanceListeners();
    }
    

    c.c. リモート処理インターフェイスにアンセンブリ属性を追加し、V1、V2_1 リスナー、V2_1 クライアントを使用します。Add an assembly attribute on remoting interfaces to use the V1, V2_1 listener, and V2_1 client.

    [assembly: FabricTransportServiceRemotingProvider(RemotingListenerVersion = RemotingListenerVersion.V2_1 | RemotingListenerVersion.V1, RemotingClientVersion = RemotingClientVersion.V2_1)]
    
    
  2. V2_1 クライアントの属性を使用して、V1 クライアントを V2_1 クライアントにアップグレードします。Upgrade the V1 client to the V2_1 client by using the V2_1 client attribute. この手順によって、クライアントは V2_1 スタックを使用するようになります。This step makes sure the client is using the V2_1 stack. クライアント プロジェクトやサービスでの変更は必要ありません。No change in the client project/service is required. 更新したインターフェイス アセンブリを使用してクライアント プロジェクトをビルドすれば十分です。Building client projects with updated interface assembly is sufficient.

  3. この手順は省略可能です。This step is optional. 属性から V1 リスナー バージョンを削除してから、V2 サービスをアップグレードします。Remove the V1 listener version from the attribute, and then upgrade the V2 service. この手順によって、サービスが V2 リスナーでのみリッスンするようにします。This step makes sure that the service is listening only on the V2 listener.

    [assembly: FabricTransportServiceRemotingProvider(RemotingListenerVersion = RemotingListenerVersion.V2_1, RemotingClientVersion = RemotingClientVersion.V2_1)]
    

リモート処理のラップ済みメッセージによるカスタム シリアル化を使用するUse custom serialization with a remoting wrapped message

リモート処理のラップ済みメッセージについては、1 つのラップ済みオブジェクトを作成し、その中にすべてのパラメーターをフィールドとして含めます。For a remoting wrapped message, we create a single wrapped object with all the parameters as a field in it. 次の手順に従います。Follow these steps:

  1. カスタム シリアル化の実装を提供するための IServiceRemotingMessageSerializationProvider インターフェイスを実装します。Implement the IServiceRemotingMessageSerializationProvider interface to provide implementation for custom serialization. このコード スニペットは、その実装がどのようなものかを示しています。This code snippet shows what the implementation looks like.

    public class ServiceRemotingJsonSerializationProvider : IServiceRemotingMessageSerializationProvider
    {
      public IServiceRemotingMessageBodyFactory CreateMessageBodyFactory()
      {
        return new JsonMessageFactory();
      }
    
      public IServiceRemotingRequestMessageBodySerializer CreateRequestMessageSerializer(Type serviceInterfaceType, IEnumerable<Type> requestWrappedType, IEnumerable<Type> requestBodyTypes = null)
      {
        return new ServiceRemotingRequestJsonMessageBodySerializer();
      }
    
      public IServiceRemotingResponseMessageBodySerializer CreateResponseMessageSerializer(Type serviceInterfaceType, IEnumerable<Type> responseWrappedType, IEnumerable<Type> responseBodyTypes = null)
      {
        return new ServiceRemotingResponseJsonMessageBodySerializer();
      }
    }
    
      class JsonMessageFactory : IServiceRemotingMessageBodyFactory
          {
    
            public IServiceRemotingRequestMessageBody CreateRequest(string interfaceName, string methodName, int numberOfParameters, object wrappedRequestObject)
            {
              return new JsonBody(wrappedRequestObject);
            }
    
            public IServiceRemotingResponseMessageBody CreateResponse(string interfaceName, string methodName, object wrappedRequestObject)
            {
              return new JsonBody(wrappedRequestObject);
            }
          }
    
    class ServiceRemotingRequestJsonMessageBodySerializer : IServiceRemotingRequestMessageBodySerializer
      {
          private JsonSerializer serializer;
    
          public ServiceRemotingRequestJsonMessageBodySerializer()
          {
            serializer = JsonSerializer.Create(new JsonSerializerSettings()
            {
              TypeNameHandling = TypeNameHandling.All
              });
            }
    
            public IOutgoingMessageBody Serialize(IServiceRemotingRequestMessageBody serviceRemotingRequestMessageBody)
           {
             if (serviceRemotingRequestMessageBody == null)
             {
               return null;
             }          
             using (var writeStream = new MemoryStream())
             {
               using (var jsonWriter = new JsonTextWriter(new StreamWriter(writeStream)))
               {
                 serializer.Serialize(jsonWriter, serviceRemotingRequestMessageBody);
                 jsonWriter.Flush();
                 var bytes = writeStream.ToArray();
                 var segment = new ArraySegment<byte>(bytes);
                 var segments = new List<ArraySegment<byte>> { segment };
                 return new OutgoingMessageBody(segments);
               }
             }
            }
    
            public IServiceRemotingRequestMessageBody Deserialize(IIncomingMessageBody messageBody)
           {
             using (var sr = new StreamReader(messageBody.GetReceivedBuffer()))
             {
               using (JsonReader reader = new JsonTextReader(sr))
               {
                 var ob = serializer.Deserialize<JsonBody>(reader);
                 return ob;
               }
             }
           }
          }
    
    class ServiceRemotingResponseJsonMessageBodySerializer : IServiceRemotingResponseMessageBodySerializer
     {
       private JsonSerializer serializer;
    
      public ServiceRemotingResponseJsonMessageBodySerializer()
      {
        serializer = JsonSerializer.Create(new JsonSerializerSettings()
        {
            TypeNameHandling = TypeNameHandling.All
          });
        }
    
        public IOutgoingMessageBody Serialize(IServiceRemotingResponseMessageBody responseMessageBody)
        {
          if (responseMessageBody == null)
          {
            return null;
          }
    
          using (var writeStream = new MemoryStream())
          {
            using (var jsonWriter = new JsonTextWriter(new StreamWriter(writeStream)))
            {
              serializer.Serialize(jsonWriter, responseMessageBody);
              jsonWriter.Flush();
              var bytes = writeStream.ToArray();
              var segment = new ArraySegment<byte>(bytes);
              var segments = new List<ArraySegment<byte>> { segment };
              return new OutgoingMessageBody(segments);
            }
          }
        }
    
        public IServiceRemotingResponseMessageBody Deserialize(IIncomingMessageBody messageBody)
        {
    
           using (var sr = new StreamReader(messageBody.GetReceivedBuffer()))
           {
             using (var reader = new JsonTextReader(sr))
             {
               var obj = serializer.Deserialize<JsonBody>(reader);
               return obj;
             }
           }
         }
     }
    
    class JsonBody : WrappedMessage, IServiceRemotingRequestMessageBody, IServiceRemotingResponseMessageBody
    {
          public JsonBody(object wrapped)
          {
            this.Value = wrapped;
          }
    
          public void SetParameter(int position, string parameName, object parameter)
          {  //Not Needed if you are using WrappedMessage
            throw new NotImplementedException();
          }
    
          public object GetParameter(int position, string parameName, Type paramType)
          {
            //Not Needed if you are using WrappedMessage
            throw new NotImplementedException();
          }
    
          public void Set(object response)
          { //Not Needed if you are using WrappedMessage
            throw new NotImplementedException();
          }
    
          public object Get(Type paramType)
          {  //Not Needed if you are using WrappedMessage
            throw new NotImplementedException();
          }
    }
    
  2. リモート処理リスナーのために、JsonSerializationProvider を使用して既定のシリアル化プロバイダーをオーバーライドします。Override the default serialization provider with JsonSerializationProvider for a remoting listener.

    protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
    {
        return new[]
        {
            new ServiceInstanceListener((c) =>
            {
                return new FabricTransportServiceRemotingListener(c, this,
                    new ServiceRemotingJsonSerializationProvider());
            })
        };
    }
    
  3. リモート処理クライアント ファクトリのために、JsonSerializationProvider を使用して既定のシリアル化プロバイダーをオーバーライドします。Override the default serialization provider with JsonSerializationProvider for a remoting client factory.

    var proxyFactory = new ServiceProxyFactory((c) =>
    {
        return new FabricTransportServiceRemotingClientFactory(
        serializationProvider: new ServiceRemotingJsonSerializationProvider());
      });
    

次のステップNext steps