基於WCF的事件發布/訂閱系統

來源:互聯網
上載者:User

在WCF中,我們可以給service contract指定callbackContract來進行回調, 而回調介面由用戶端實現。為了說明問題,我們設計了一個簡單的scenario。

scenario description:

假設WCF service提供簡單的AddTo(),即進行累積。用戶端通過proxy消費這個service並將計算結果發布到所有註冊了回調通道的其他用戶端。

回調介面設計如下:

Code
<!-- <br /><br />Code highlighting produced by ActiproCodeHighlighter (freeware)<br/>http://www.CodeHighlighter.com/<br /><br />-->[ServiceContract]
    public interface ICaculatorCallBack
    {
        [OperationContract(IsOneWay = true)]
        void Equals(int result);
    }

服務介面如下:

<!-- <br /><br />Codehighlighting produced by Actipro CodeHighlighter (freeware)<br/>http://www.CodeHighlighter.com/<br /><br />-->[ServiceContract(CallbackContract=typeof(ICaculatorCallBack),SessionMode=SessionMode.Required)]   
    public interface ICaculatorService
    {
        [OperationContract(IsOneWay=true)]
        void AddTo(int n);

 

        [OperationContract(IsOneWay

=true)]
        void Register();
    }

服務類型設計如下:

 

Code
<!-- <br /><br />Code highlighting produced by ActiproCodeHighlighter (freeware)<br/>http://www.CodeHighlighter.com/<br /><br />-->using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;

 

 

namespace WCFCallBack
{
    public class AddEventAgrs : EventArgs
    {
       public int result;
    }

 

    [ServiceBehavior(InstanceContextMode

=InstanceContextMode.PerSession)]
    class CaculatorService:ICaculatorService
    {
        public delegate void AddEventHandler(object sender, AddEventAgrs e);
        public static event AddEventHandler OnAddCompleted;
        public ICaculatorCallBack callback;
        public int result;

 

 

public CaculatorService()
        {
            result = 0;           
        }

 

 

public void Register()
        {
            callback = System.ServiceModel.OperationContext.Current.GetCallbackChannel<ICaculatorCallBack>();
            OnAddCompleted += new AddEventHandler(CaculatorService_OnAddCompleted);
        }

 

 

void CaculatorService_OnAddCompleted(object sender, AddEventAgrs e)
        {
            Console.WriteLine("the OnAdd event has been triggered");
            callback.Equals(e.result);
        }

 

 

public void BroadAddEvent(AddEventAgrs e, AddEventHandler temp)
        {
            if (OnAddCompleted != null)
            {
                foreach (AddEventHandler handler in temp.GetInvocationList())
                {
                    handler.BeginInvoke(this, e, null, null);
                }
            }
        }
       
        public void AddTo(int n)
        {
            AddEventAgrs e = new AddEventAgrs();
            this.result += n;
            e.result = result;
            BroadAddEvent(e, OnAddCompleted);
        }
    }
}

回調介面和服務契約非常簡單,下面對serviceType作簡單說明:

關於AddEventHandler:

當用戶端調用AddTo這個服務的時候,伺服器端開始計算,當計算完畢之後,然後開始廣播並且調用各個用戶端的回調實現。為了捕獲計算完畢這個動作,因此我們必須定義一種類型的事件控制代碼並且申明相應類型的事件,因此本例中我們定義了一種AddEventHandle類型的事件OnAddCompleted

OnAddCompleted事件觸發的時機:

那麼OnAddCompleted事件是什麼時候觸發的呢?是在用戶端消費AddTo服務的時候。 從AddToimplementation中我們可以看到:我們先將結算結果儲存,並建立一個自訂事件,將計算結果儲存至事件Args中,然後開始廣播該事件(BroadAddEvent)。廣播該事件的作用就是讓所有註冊了該事件(即消費了Register服務)的用戶端開始調用其事件處理常式(CaculatorService_OnAddCompleted)。在該事件處理常式中,然後開始調用用戶端的callbacb。

這就是整個利用callback機制進行廣播的過程。

下面我們實現一個簡單的用戶端callback.如下:

Code
<!-- <br /><br />Code highlighting produced by ActiproCodeHighlighter (freeware)<br/>http://www.CodeHighlighter.com/<br /><br />-->class CallBack:ICaculatorServiceCallback
    {
        public void Equals(int n)
        {
           Console.WriteLine("this callback is implemented on client,the callback result is {0}", n.ToString());
        }
    }

用戶端1主程式如下:

Code
<!-- <br /><br />Code highlighting produced by ActiproCodeHighlighter (freeware)<br/>http://www.CodeHighlighter.com/<br /><br />-->using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

 

 

namespace WCFClient
{
    class Program
    {
        static void showMenu()
        {
            Console.WriteLine("Operation MENU\n--------------------");
            Console.Write("A:(Add) \nE:(exit):");
        }

 

 

static void Main(string[] args)
        {
          
            try
            {
                showMenu();

 

                System.ServiceModel.InstanceContext callbackInstance 

= new System.ServiceModel.InstanceContext(new CallBack());
                CaculatorServiceClient proxy = new CaculatorServiceClient(callbackInstance);
                proxy.Open();
                proxy.Register();

 

 

string answer = Console.ReadLine();
                while (answer.ToUpper() != "E")
                {
                    Console.Write("Please input the number to add:");
                    int n = Convert.ToInt16(Console.ReadLine());
                    proxy.AddTo(n);
                    System.Threading.Thread.Sleep(2000);
                    showMenu();
                    answer = Console.ReadLine();
                }
                proxy.Close();
              
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.ReadLine();
            }
            
        }
    }
}

用戶端2回調及主程式如下:

Code
<!-- <br /><br />Code highlighting produced by ActiproCodeHighlighter (freeware)<br/>http://www.CodeHighlighter.com/<br /><br />--> class CallBack:ICaculatorServiceCallback
    {
        public void Equals(int n)
        {
            Console.WriteLine("I have received a broadcasting news,the callback result is {0}", n.ToString());
        }
    }
 class Program
    {
        static void Main(string[] args)
        {
            try
            {
                System.ServiceModel.InstanceContext callbackInstance = new System.ServiceModel.InstanceContext(new CallBack());
                CaculatorServiceClient proxy = new CaculatorServiceClient(callbackInstance);
                proxy.Open();
                Console.WriteLine("I am another listener, and I am receiving all broadcasting news\n--------------------------------------------");               
                proxy.Register();
                Console.ReadLine();
                proxy.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.ReadLine();
            }
            
        }
    }

運行screenshot如下:

 總結:

事件發布/訂閱模型有著廣泛應用,比如即時任務調度,多人線上遊戲,即時聊天,軟體版本的自動更新等等。只有你想不到,沒有你做不到:)

欲下載本文原始碼,請點擊此處

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.