天天看點

Caliburn.Micro學習筆記(三)----事件聚合IEventAggregator和 Ihandle<T>

Caliburn.Micro學習筆記目錄

今天 說一下Caliburn.Micro的IEventAggregator和IHandle<T>分成兩篇去講這一篇寫一個簡單的例子

看一它的的實作和源碼

下一篇用它們做一個多語言的demo

這兩個是事件的訂閱和廣播,很強大,但用的時候要小心發生不必要的沖突。

先看一下它的實作思想

Caliburn.Micro學習筆記(三)----事件聚合IEventAggregator和 Ihandle&lt;T&gt;

在Caliburn.Micro裡EventAggregator要以單例的形式出現這樣可以做到對廣播做到統一的管理

對象實作IHand<T>接口後通過EventAggregator的subsribe方法把自己加入到Handler集合中這樣就能接叫資訊

能過EventAggregator.Publish(object obj)方法去發送廣播

源碼: CaliburnIHandle.rar

先看一下個小demo再去分析它的源碼是怎麼實作的

效果

Caliburn.Micro學習筆記(三)----事件聚合IEventAggregator和 Ihandle&lt;T&gt;
Caliburn.Micro學習筆記(三)----事件聚合IEventAggregator和 Ihandle&lt;T&gt;
先寫一個消息類,這個類隻是做一個IHandle<T>的類型應用沒有什麼實際意義

class MyMessage
    {
        public string Str
        {
            get;
            set;
        }
        public override string ToString()
        {
            return Str;
        }
    }      

建一個窗體MainView和一個ViewModel類

<Window x:Class="CaliburnIHandle.MyViews.MyMainView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MyMainView" Height="300" Width="300">
    <StackPanel>
        <TextBox x:Name="StrMessage" Margin="5"/>
        <Button x:Name="OpenOneWin" Content="OpenOneWin" Margin="5"/>       
        <Button Content="Publish" x:Name="Publish" Margin="5"/>
    </StackPanel>
</Window>      

窗體有一個textBox顯示消息。一個button打開窗體一個釋出消息

再看一下ViewModel

實作 了兩個IHandle<T> 一個是string 類型一個是我們自己定義的MyMessage

MainViewMode釋出string類型的廣播也接收string類型和MyMessage類型的消息

[Export(typeof(IShell))]
    class MyMainViewModel : PropertyChangedBase, IHandle<string>,IHandle<MyMessage>
    {
        readonly IEventAggregator _events;
        readonly IWindowManager _windowManager;
        string strMessage;
        public string StrMessage
        {
            get
            {
                return strMessage;
            }
            set
            {
                strMessage = value;
                NotifyOfPropertyChange(() => StrMessage);
            }
        }
       

        [ImportingConstructor]
        public MyMainViewModel(IEventAggregator e,IWindowManager win)
        {
            _events = e;
            _events.Subscribe(this);
            _windowManager = win;
        }



        public void Handle(string message)
        {
            StrMessage = message;
        }
        public void Handle(MyMessage message)
        {
            StrMessage = message.ToString();
        }

        #region 
        public void Publish()
        {
            _events.Publish(StrMessage);
        }
        #endregion

        #region 打開窗體
        public void OpenOneWin()
        {
            OneCViewModel _one=new OneCViewModel();
            _windowManager.ShowWindow(_one);
        }
        #endregion      

再建一個窗體做接收和廣播

它隻接收string類型的消息和釋出MyMessage類型的消息

<UserControl x:Class="CaliburnIHandle.MyViews.OneCView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             
             Height="300" Width="300">
    <StackPanel>
        <TextBlock FontSize="13" HorizontalAlignment="Center">1</TextBlock>
        <TextBox Margin="5" x:Name="OneMessage"></TextBox>
        <Button Margin="5" x:Name="OnePublish" Content="Publish"/>
    </StackPanel>
</UserControl>      
using Caliburn.Micro;
using CaliburnIHandle.CommonC;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;

namespace CaliburnIHandle.MyViewModels
{
    [Export(typeof(OneCViewModel))]
    class OneCViewModel : PropertyChangedBase, IHandle<string>
    {
        readonly IEventAggregator _event;
        string oneMessage;
        public string OneMessage
        {
            get
            {
                return oneMessage;
            }
            set
            {
                oneMessage = value;
                NotifyOfPropertyChange(() => OneMessage);
            }
        }
        public OneCViewModel()
        {
            _event = IoC.Get<IEventAggregator>();
            _event.Subscribe(this);
        }


        public void OnePublish()
        {
            _event.Publish(new MyMessage { Str = OneMessage + " One!" });
        }

        public void Handle(string message)
        {
            OneMessage = message;
        }
    }
}      

這是一個很簡單的例子我們看一下Caliburn.Micro源碼它是怎麼實作的

看一下IHandle<T>接口

public interface IHandle<TMessage> : IHandle {  //don't use contravariance here
        /// <summary>
        ///   Handles the message.
        /// </summary>
        /// <param name = "message">The message.</param>
        void Handle(TMessage message);
    }      

IHandle<T>隻有一個處理T事件的的方法

EventAggregator類通過

/// <summary>
        ///   Subscribes an instance to all events declared through implementations of <see cref = "IHandle{T}" />
        /// </summary>
        /// <param name = "subscriber">The instance to subscribe for event publication.</param>
        public virtual void Subscribe(object subscriber) {
            if (subscriber == null) {
                throw new ArgumentNullException("subscriber");
            }
            lock(handlers) {
                if (handlers.Any(x => x.Matches(subscriber))) {
                    return;
                }

                handlers.Add(new Handler(subscriber));
            }
        }      

把訂閱的類放到Handlers集合裡

再通過Publish釋出相應的消息

/// <summary>
        ///   Publishes a message.
        /// </summary>
        /// <param name = "message">The message instance.</param>
        /// <remarks>
        ///   Does not marshall the the publication to any special thread by default.
        /// </remarks>
        public virtual void Publish(object message) {
            if (message == null) {
                throw new ArgumentNullException("message");
            }
            Publish(message, PublicationThreadMarshaller);
        }

        /// <summary>
        ///   Publishes a message.
        /// </summary>
        /// <param name = "message">The message instance.</param>
        /// <param name = "marshal">Allows the publisher to provide a custom thread marshaller for the message publication.</param>
        public virtual void Publish(object message, Action<System.Action> marshal) {
            if (message == null){
                throw new ArgumentNullException("message");
            }
            if (marshal == null) {
                throw new ArgumentNullException("marshal");
            }

            Handler[] toNotify;
            lock (handlers) {
                toNotify = handlers.ToArray();
            }

            marshal(() => {
                var messageType = message.GetType();

                var dead = toNotify
                    .Where(handler => !handler.Handle(messageType, message))
                    .ToList();

                if(dead.Any()) {
                    lock(handlers) {
                        dead.Apply(x => handlers.Remove(x));
                    }
                }
            });
        }      

作者:李鵬

出處:http://www.cnblogs.com/li-peng/

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。