zoukankan      html  css  js  c++  java
  • Caliburn.Micro学习笔记(三)----事件聚合IEventAggregator和 Ihandle<T>

    Caliburn.Micro学习笔记(三)----事件聚合IEventAggregator和 Ihandle<T>

     

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

    看一它的的实现和源码

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

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

    先看一下它的实现思想

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

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

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

    源码: CaliburnIHandle.rar

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

    效果

          

    先写一个消息类,这个类只是做一个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));
                        }
                    }
                });
            }
    复制代码
    作者:李鹏
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    BZOJ 3295 【CQOI2011】 动态逆序对
    POJ 3714 Raid
    树状数组区间修改加区间查询
    codevs 2606 约数和问题
    UOJ #150 【NOIP2015】 运输计划
    分享知识-快乐自己:IDEA 导入(web)项目并部署到 Tomcat
    分享知识-快乐自己:配置(各种)环境变量
    分享知识-快乐自己:什么是MVC
    分享知识-快乐自己:SpringBoot 使用注解API的方式定义启动端口号
    分享知识-快乐自己:Oracle中定义及使用同义词
  • 原文地址:https://www.cnblogs.com/nepulgh/p/7128840.html
Copyright © 2011-2022 走看看