MVVMLight消息通知实现机制详解(二)

  接上文 MVVMLight消息通知实现机制详解(一)

  1. 该工具的内部主要逻辑是以字典模式进行储存持有订阅对象设置的传入参数Type类型、Key值、Action、Target(订阅对象本身)
  2. 在发生订阅事件和触发订阅事件时都会调用通过查询上述字典进行匹配,找到Key值相同&&Type类型相同的值,执行target的action并传入参数
  3. 扩展1:可发生没有key值的订阅事件,只要传参类型相同就可以
  4. 扩展2:可发生静态类的订阅事件,其内部有判断是否为static,static时target可为空

 

  找到源码看到,订阅事件部分代码:

  public virtual void Register<TMessage>( object recipient,object token,bool receiveDerivedMessagesToo,Action<TMessage> action,bool keepTargetAlive = false)
        {
            lock (_registerLock)
            {
                var messageType = typeof(TMessage);

                Dictionary<Type, List<WeakActionAndToken>> recipients;

                if (receiveDerivedMessagesToo)
                {
                    if (_recipientsOfSubclassesAction == null)
                    {
                        _recipientsOfSubclassesAction = new Dictionary<Type, List<WeakActionAndToken>>();
                    }

                    recipients = _recipientsOfSubclassesAction;
                }
                else
                {
                    if (_recipientsStrictAction == null)
                    {
                        _recipientsStrictAction = new Dictionary<Type, List<WeakActionAndToken>>();
                    }

                    recipients = _recipientsStrictAction;
                }

                lock (recipients)
                {
                    List<WeakActionAndToken> list;

                    if (!recipients.ContainsKey(messageType))
                    {
                        list = new List<WeakActionAndToken>();
                        recipients.Add(messageType, list);
                    }
                    else
                    {
                        list = recipients[messageType];
                    }

                    var weakAction = new WeakAction<TMessage>(recipient, action, keepTargetAlive);

                    var item = new WeakActionAndToken
                    {
                        Action = weakAction,
                        Token = token
                    };

                    list.Add(item);
                }
            }

            RequestCleanup();
        }

  以上是源码上订阅事件代码,其具体逻辑如下:

  1. 以Dictionary<Type, List<WeakActionAndToken>> 类型持有数据,对每一个订阅事件都是先在Dictionary的Key上查找是否存在该传参类型,不存在就添加该类型(Add(type,new List<WeakActionAndToken>)),存在就添加到该类型对应的Value列表中

  2. 在其Value值上是List<WeakActionAndToken>类型,WeakActionAndToken包含本次订阅事件的Action和Key值

  

  源码Send部分代码:

 private void SendToTargetOrType<TMessage>(TMessage message, Type messageTargetType, object token)
        {
            var messageType = typeof(TMessage);

            if (_recipientsOfSubclassesAction != null)
            {
                // Clone to protect from people registering in a "receive message" method
                // Correction Messaging BL0008.002
                var listClone =
                    _recipientsOfSubclassesAction.Keys.Take(_recipientsOfSubclassesAction.Count()).ToList();

                foreach (var type in listClone)
                {
                    List<WeakActionAndToken> list = null;

                    if (messageType == type
                        || messageType.IsSubclassOf(type)
                        || type.IsAssignableFrom(messageType))
                    {
                        lock (_recipientsOfSubclassesAction)
                        {
                            list = _recipientsOfSubclassesAction[type].Take(_recipientsOfSubclassesAction[type].Count()).ToList();
                        }
                    }

                    SendToList(message, list, messageTargetType, token);
                }
            }

            if (_recipientsStrictAction != null)
            {
                List<WeakActionAndToken> list = null;

                lock (_recipientsStrictAction)
                {
                    if (_recipientsStrictAction.ContainsKey(messageType))
                    {
                        list = _recipientsStrictAction[messageType]
                            .Take(_recipientsStrictAction[messageType].Count())
                            .ToList();
                    }
                }

                if (list != null)
                {
                    SendToList(message, list, messageTargetType, token);
                }
            }

            RequestCleanup();
        }

  以上是源码上发送事件消息代码,其具体逻辑如下:

  • 根据传参Type值在Dictionary<Type, List<WeakActionAndToken>>上查找对应List<WeakActionAndToken>列表
  • 然后对该列表内WeakActionAndToken进行匹配,对应Key值是否相同
  • 找到Key值相同的WeakActionAndToken执行其Action

 

  备注:在Send()部分应该加异步发送消息,个人自测频率太快的调用会造成卡顿延迟(类似心跳包这种就有点费劲)

  源码:MVVMLight的消息发送工具源码,可单独使用

 

转载于:https://www.cnblogs.com/Khan-Sadas/p/10072214.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MVVMLight 提供了一个名为 `Messenger` 的类,用于实现消息传递机制。通过 `Messenger` 类,可以在不同的 ViewModel 之间发送和接收消息实现模块解耦和相互通信。 以下是使用 MVVMLight消息传递机制的基本步骤: 1. 创建发送消息的 ViewModel: ```csharp using GalaSoft.MvvmLight; using GalaSoft.MvvmLight.Command; using GalaSoft.MvvmLight.Messaging; namespace MVVMLightDemo.ViewModels { public class SenderViewModel : ViewModelBase { public RelayCommand SendMessageCommand { get; private set; } public SenderViewModel() { SendMessageCommand = new RelayCommand(SendMessage); } private void SendMessage() { Messenger.Default.Send<string>("Hello from SenderViewModel!"); } } } ``` 在上述代码中,我们创建了一个名为 `SenderViewModel` 的 ViewModel,并在其中定义了一个 `SendMessageCommand`,当该命令执行时,会发送一个字符串类型的消息。 2. 创建接收消息的 ViewModel: ```csharp using GalaSoft.MvvmLight; using GalaSoft.MvvmLight.Messaging; namespace MVVMLightDemo.ViewModels { public class ReceiverViewModel : ViewModelBase { public string Message { get; private set; } public ReceiverViewModel() { Messenger.Default.Register<string>(this, HandleMessage); } private void HandleMessage(string message) { Message = message; RaisePropertyChanged(nameof(Message)); } } } ``` 在上述代码中,我们创建了一个名为 `ReceiverViewModel` 的 ViewModel,并在构造函数中使用 `Messenger.Default.Register` 方法注册对字符串类型消息的处理方法。当接收到消息时,`HandleMessage` 方法会被调用,并将消息存储在 `Message` 属性中。 3. 在视图中绑定接收到的消息: ```xaml <Window x:Class="MVVMLightDemo.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:MVVMLightDemo" xmlns:ViewModels="clr-namespace:MVVMLightDemo.ViewModels" Title="MVVMLight Demo" Height="350" Width="525"> <Window.DataContext> <ViewModels:ReceiverViewModel /> </Window.DataContext> <StackPanel> <TextBlock Text="{Binding Message}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="24" /> </StackPanel> </Window> ``` 在上述代码中,我们将视图的 DataContext 绑定到 `ReceiverViewModel`,并将 `Message` 属性绑定到 TextBlock 的 Text 属性。这样,当接收到消息时,TextBlock 中将显示消息的内容。 通过上述步骤,我们实现了在两个 ViewModel 之间的消息传递。当发送消息的 ViewModel 执行 `SendMessageCommand` 时,消息将发送到 `ReceiverViewModel`,并由 `HandleMessage` 方法处理。处理后的消息将存储在 `Message` 属性中,并通过数据绑定在视图中显示出来。 请注意,在使用 MVVMLight消息传递机制时,需要确保注册和注销相应的消息处理方法,以避免内存泄漏。可以在接收消息的 ViewModel 的构造函数中注册消息处理方法,并在 ViewModel 销毁时调用 `Messenger.Default.Unregister` 方法注销消息处理方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值