Caliburn.Micro學習筆記目錄
今天 說一下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));
}
}
});
}
作者:李鵬
出處:http://www.cnblogs.com/li-peng/
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。