事件聚合IEventAggregator和 Ihandle

-事件聚合IEventAggregator和 Ihandle<T>

 

今天 说一下Caliburn.Micro的IEventAggregator和IHandle<T>分成两篇去讲这一篇写一个简单的例子

看一它的的实现和源码

下一篇用它们做一个多语言的demo

这两个是事件的订阅和广播,很强大,但用的时候要小心发生不必要的冲突。

先看一下它的实现思想

事件聚合IEventAggregator和 Ihandle<T>

在Caliburn.Micro里EventAggregator要以单例的形式出现这样可以做到对广播做到统一的管理

对象实现IHand<T>接口后通过EventAggregator的subsribe方法把自己加入到Handler集合中这样就能接叫信息

能过EventAggregator.Publish(object obj)方法去发送广播

源码: CaliburnIHandle.rar

先看一下个小demo再去分析它的源码是怎么实现的

效果

事件聚合IEventAggregator和 Ihandle<T>      事件聚合IEventAggregator和 Ihandle<T>

先写一个消息类,这个类只是做一个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));

                    }

                }

            });

        }
复制代码

 

作者: 李鹏

你可能感兴趣的:(event)