共用方式為


如何:動態更新

本主題概要說明建立和動態更新路由組態所需的基本步驟。 在此範例中,初始路由組態是從組態檔取得,並且會將所有訊息路由傳送至 regularCalc 計算機服務。不過,該組態接著會以程式設計的方式更新,以變更 roundingCalc 服務的目的端點。

注意

在許多實作中,組態將完全為動態,而且不會倚賴預設組態。不過,在某些情況下,例如本主題中的情況,會希望服務啟動時為預設的組態狀態。

注意

動態更新只會在記憶體中發生,而不會導致修改組態檔。

regularCalc 和 roundingCalc 兩者都支援相同的加、減、乘、除作業。不過,roundingCalc 會先將所有計算四捨五入至最接近的整數值再傳回。 組態檔可用來設定讓服務將所有訊息路由傳送至 regularCalc 服務。 路由服務啟動後,ApplyConfiguration 可用來重新設定服務,使其將訊息路由傳送至 roundingCalc 服務。

實作初始組態

  1. 藉由指定服務所公開的服務端點,建立基本路由服務組態。 下列範例定義將用於接收訊息的單一服務端點。 此外,還會定義用來將訊息傳送至 regularCalc 的用戶端端點。

    <services>
      <service behaviorConfiguration="routingConfiguration"
               name="System.ServiceModel.Routing.RoutingService">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost/routingservice/router" />
          </baseAddresses>
        </host>
        <!--Set up the inbound endpoint for the Routing Service-->
        <endpoint address="calculator"
                  binding="wsHttpBinding"
                  name="routerEndpoint"
                  contract="System.ServiceModel.Routing.IRequestReplyRouter" />
      </service>
    </services>
    <client>
    <!--set up the destination endpoint-->
      <endpoint name="regularCalcEndpoint"
                address="net.tcp://localhost:9090/servicemodelsamples/service/"
                binding="netTcpBinding"
                contract="*" />
    </client>
    
  2. 定義用於傳送訊息至目的地端點的篩選條件。 在此範例中,MatchAll 篩選條件會用來將所有訊息路由傳送至之前定義的 regularCalcEndpoint。 下列範例會定義篩選條件和篩選資料表。

    <filters>
      <!--define the message filter-->
      <filter name="MatchAllFilter" filterType="MatchAll"/>
    </filters>
    <filterTables>
      <filterTable name="filterTable1">
          <!--add the filter to the message filter table-->
          <add filterName="MatchAllFilter" endpointName="regularCalcEndpoint"/>
      </filterTable>
    </filterTables>
    
  3. 若要針對包含在篩選資料表之篩選條件的傳入訊息加以評估,您必須使用路由行為產生篩選資料表與服務端點的關聯。 下列範例示範如何將 "filterTable1" 與服務端點相關聯。

    <behaviors>
      <!--default routing service behavior definition-->
      <serviceBehaviors>
        <behavior name="routingConfiguration">
          <routing filterTableName="filterTable1" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    

實作動態組態

路由服務的動態組態只能透過建立新的 RoutingConfiguration,並使用 ApplyConfiguration 取代目前組態的方式,在程式碼中執行。 在此範例中,路由服務會在主控台應用程式內自我裝載。 應用程式啟動後,您可以在主控台視窗中輸入 ‘regular’ 或 ‘rounding’ 來設定路由傳送訊息的目的端點,藉此修改路由組態。若輸入 ‘regular’ 則為 regularCalc,若輸入 ‘rounding’ 則為 roundingCalc。

  1. 必須新增下列 using 指示詞,才能支援路由服務。

    using System;
    using System.Collections.Generic;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Description;
    using System.ServiceModel.Dispatcher;
    using System.ServiceModel.Routing;
    
  2. 下列程式碼可用來自我裝載路由服務做為主控台應用程式。 這樣做會使用前一個步驟中描述的組態初始化路由服務,該組態包含在應用程式組態檔內。 while 迴圈包含的程式碼即可用來變更路由組態。

    // Host the service within this EXE console application.
    public static void Main()
    {
        // Create a ServiceHost for the CalculatorService type.
        using (ServiceHost serviceHost =
            new ServiceHost(typeof(RoutingService)))
        {
            // Open the ServiceHost to create listeners
            // and start listening for messages.
            Console.WriteLine("The Routing Service configured, opening....");
            serviceHost.Open();
            Console.WriteLine("The Routing Service is now running.");
             Console.WriteLine("Type 'quit' to terminate router.");
             Console.WriteLine("<ENTER> to change routing configuration.");
             while (Console.ReadLine() != "quit")
             {
            ....
            }
        }
    }
    
  3. 若要動態更新路由組態,則必須建立新的路由組態。 其中必須包含新路由組態需要的所有端點、篩選條件和篩選資料表,因為該組態會完全取代現有的路由組態。 為了使用新的路由組態,您必須叫用 ApplyConfiguration 並且傳遞新的組態。

    將下列程式碼加入至之前定義的 while 迴圈,即可根據使用者輸入重新設定服務。

    Console.WriteLine("Enter 'regular' or 'rounding' to set the destination endpoint:");
    string destEndpoint = Console.ReadLine();
    // Create a new RoutingConfiguration
    RoutingConfiguration rc = new RoutingConfiguration();
    // Determine the endpoint to configure for
    switch (destEndpoint)
    {
        case "regular":
            // Define the destination endpoint
            ServiceEndpoint regularCalc = new ServiceEndpoint(
               ContractDescription.GetContract(typeof(IRequestReplyRouter)),
               new NetTcpBinding(),
               new EndpointAddress("net.tcp://localhost:9090/servicemodelsamples/service/"));
            // Create a MatchAll filter and add to the filter table
            rc.FilterTable.Add(new MatchAllMessageFilter(), new List<ServiceEndpoint> { regularCalc });
            // Use ApplyConfiguration to update the Routing Service
            serviceHost.Extensions.Find<RoutingExtension>().ApplyConfiguration(rc);
            Console.WriteLine("Applied new routing configuration.");
            break;
        case "rounding":
            // Define the destination endpoint
            ServiceEndpoint roundingCalc = new ServiceEndpoint(
               ContractDescription.GetContract(typeof(IRequestReplyRouter)),
               new NetTcpBinding(),
               new EndpointAddress("net.tcp://localhost:8080/servicemodelsamples/service/"));
            // Create a MatchAll filter and add to the filter table
            rc.FilterTable.Add(new MatchAllMessageFilter(), new List<ServiceEndpoint> { roundingCalc });
            // Use ApplyConfiguration to update the Routing Service
            serviceHost.Extensions.Find<RoutingExtension>().ApplyConfiguration(rc);
            Console.WriteLine("Applied new routing configuration.");
            break;
        default:
            Console.WriteLine("Incorrect value entered, no change.");
            break;
    }
    

    注意

    由於提供新 RoutingConfiguration 的方法包含在 RoutingExtension 服務延伸模組內,因此可以在擁有或能夠取得 ServiceHost 或 ServiceExtensions 參考 (例如在另一個 ServiceExtension 中) 的 WCF 擴充性模型中任何位置提供新的 RoutingConfiguration 物件。

範例 1

以下是此範例中所使用主控台應用程式的完整清單:

//-----------------------------------------------------------------
//  Copyright (c) Microsoft Corporation.  All Rights Reserved.
//-----------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Routing;

namespace Microsoft.Samples.AdvancedFilters
{
    public class Router
    {
        // Host the service within this EXE console application.
        public static void Main()
        {
            // Create a ServiceHost for the CalculatorService type.
            using (ServiceHost serviceHost =
                new ServiceHost(typeof(RoutingService)))
            {
                // Open the ServiceHost to create listeners
                // and start listening for messages.
                Console.WriteLine("The Routing Service configured, opening....");
                serviceHost.Open();
                Console.WriteLine("The Routing Service is now running.");
                Console.WriteLine("Type 'quit' to terminate router.");
                Console.WriteLine("<ENTER> to change routing configuration.");
                while (Console.ReadLine() != "quit")
                {
                    Console.WriteLine("Enter 'regular' or 'rounding' to set the destination endpoint:");
                    string destEndpoint = Console.ReadLine();
                    // Create a new RoutingConfiguration
                    RoutingConfiguration rc = new RoutingConfiguration();
                    // Determine the endpoint to configure for
                    switch (destEndpoint)
                    {
                        case "regular":
                            // Define the destination endpoint
                            ServiceEndpoint regularCalc = new ServiceEndpoint(
                            ContractDescription.GetContract(typeof(IRequestReplyRouter)),
                            new NetTcpBinding(),
                            new EndpointAddress("net.tcp://localhost:9090/servicemodelsamples/service/"));
                            // Create a MatchAll filter and add to the filter table
                            rc.FilterTable.Add(new MatchAllMessageFilter(), new List<ServiceEndpoint> { regularCalc });
                            // Use ApplyConfiguration to update the Routing Service
                            serviceHost.Extensions.Find<RoutingExtension>().ApplyConfiguration(rc);
                            Console.WriteLine("Applied new routing configuration.");
                            break;
                        case "rounding":
                            // Define the destination endpoint
                            ServiceEndpoint roundingCalc = new ServiceEndpoint(
                                ContractDescription.GetContract(typeof(IRequestReplyRouter)),
                                new NetTcpBinding(),
                                new EndpointAddress("net.tcp://localhost:8080/servicemodelsamples/service/"));
                            // Create a MatchAll filter and add to the filter table
                            rc.FilterTable.Add(new MatchAllMessageFilter(), new List<ServiceEndpoint> { roundingCalc });
                            // Use ApplyConfiguration to update the Routing Service
                            serviceHost.Extensions.Find<RoutingExtension>().ApplyConfiguration(rc);
                            Console.WriteLine("Applied new routing configuration.");
                            break;
                        default:
                            Console.WriteLine("Incorrect value entered, no change.");
                            break;
                    }
                }
            }
        }
    }
}

範例 2

以下是此範例中所使用組態檔的完整清單:

<?xml version="1.0" encoding="utf-8" ?>
<!-- Copyright (c) Microsoft Corporation. All rights reserved -->
<configuration>
  <system.serviceModel>
    <services>
      <service behaviorConfiguration="routingConfiguration"
               name="System.ServiceModel.Routing.RoutingService">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost/routingservice/router" />
          </baseAddresses>
        </host>
        <!--Set up the inbound endpoint for the Routing Service-->
        <endpoint address="calculator"
                  binding="wsHttpBinding"
                  name="routerEndpoint"
                  contract="System.ServiceModel.Routing.IRequestReplyRouter" />
      </service>
    </services>
    <behaviors>
      <!--default routing service behavior definition-->
      <serviceBehaviors>
        <behavior name="routingConfiguration">
          <routing filterTableName="filterTable1" />
        </behavior>
      </serviceBehaviors>
    </behaviors>

    <client>
<!--set up the destination endpoint-->
      <endpoint name="regularCalcEndpoint"
                address="net.tcp://localhost:9090/servicemodelsamples/service/"
                binding="netTcpBinding"
                contract="*" />
    </client>
    <routing>

      <filters>
        <!--define the message filter-->
        <filter name="MatchAllFilter" filterType="MatchAll"/>
      </filters>
      <filterTables>
        <filterTable name="filterTable1">
            <!--add the filter to the message filter table-->
            <add filterName="MatchAllFilter" endpointName="regularCalcEndpoint"/>
        </filterTable>
      </filterTables>
    </routing>
  </system.serviceModel>
</configuration>

另請參閱