跳转至

常用消息类型 Messages

工具包为我们提供了几个常用的消息类型,包括:

  • ValueChangedMessage
  • PropertyChangedMessage
  • RequestMessage

这几种消息类型有的拥有一些特殊的功能,下面将会详细介绍。如果我们希望对消息类型进行定制或扩展,那么可以继承这些消息类型,并实现自己的消息类型。

自定义 Message

工具包中的 IMessenger 接口约定的 SendRegister 等泛型方法,并没有要求消息的种类满足任何条件(比如继承自某个基类),所以完全可以自由地实现任何消息类型。

比如这里,我们用 C# 9.0 为我们带来的 record 类型快速声明一个消息类型,并使用:

// 声明一个消息类型
public record MyMessage(string Content);

// 发送消息
WeakReferenceMessenger.Default.Send(new MyMessage("Hello World!"));

// 接收消息
WeakReferenceMessenger.Default.Register<MyMessage>(this, message =>
{
    Console.WriteLine(message.Content);
});

ValueChangedMessage

ValueChangedMessage 是一个最基本的消息类型,它包含一个 Value 属性,用于存储消息的值。如果希望发送一个用于通知某个值发生变化的消息,可以使用 ValueChangedMessage

此外,还可以继承这个类,从而实现自己的消息类型。比如:

public class MyMessage : ValueChangedMessage<string>
{
    public MyMessage(string value) : base(value)
    {
    }
}

// 发送消息
WeakReferenceMessenger.Default.Send(new MyMessage("Hello World!"));

// 接收消息
WeakReferenceMessenger.Default.Register<MyMessage>(this, message =>
{
    Console.WriteLine(message.Value);
});

没有接收者?

对于一个不需要回复的消息(不是 RequestMessage 或其子类),如果没有任何接收者,那么 Send 方法将会正常运行,且不会有任何效果。

RequestMessage

这是一个特殊的消息类型。如果 Send 方法发送的是这个类(或它的子类),那么 Send 方法将拥有一个返回值,这个返回值就是消息的接收者回复的消息。此时,消息的接收者也能够通过消息上的 Reply 方法回复消息的发送者。比如:

// 注册消息接收者
WeakReferenceMessenger.Default.Register<MyRequestMessage>(
    new object(),
    (_, m) =>
    {
        // 收到消息后,会进行简单的判断,并回复消息
        if (m.Content == "Nice to meet you!")
            m.Reply("Nice to meet you, too!");
        else
            m.Reply("Yes?");
    }
);

// 发送消息并查看回复的消息内容
var res1 = WeakReferenceMessenger.Default.Send(new MyRequestMessage("Hello!"));
Console.WriteLine(res1.Response);

var res2 = WeakReferenceMessenger.Default.Send(new MyRequestMessage("Nice to meet you!"));
Console.WriteLine(res2.Response);

// 声明一个自定义消息类型
public class MyRequestMessage : RequestMessage<string>
{
    public string Content { get; init; }

    public MyRequestMessage(string content)
    {
        Content = content;
    }
}

然后就能在控制台看到这样的输出内容:

Yes?
Nice to meet you, too!

没有回复者?

由于在发送 RequestMessage 时,消息的接收者需要等待回复消息,所以如果此时没有接受者,那么可能会出现问题。具体来说,单纯调用 Send 不会报错,但是如果试图访问 response.Response则会抛出异常。原因是并没有任何接收者提供了回复。

有多个回复者?

如果有多个接收者回复了消息,那么将会报错。此时正确的做法是,可以从 RequestMessage 上的 HasReceivedResponse 属性判断是否已经有接收者回复了消息。如果已经有接收者回复了消息,那么这个属性的值将会为 true

PropertyChangedMessage

PropertyChangedMessage 是一个用于通知属性发生变化的消息类型,它包含一个 PropertyName 属性,用于存储属性的名称。如果希望发送一个用于通知某个属性发生变化的消息,可以使用 PropertyChangedMessage

这个类通常配合 ObservableRecipientBroadcast 方法使用,详见 相关章节

评论