重要
MessagingCenter 在 .NET 10 中已弃用。 建议从 CommunityToolkit.Mvvm 包迁移到WeakReferenceMessenger,或使用具有简单方案弱引用的事件。 有关详细信息,请参阅 Messenger。
MessagingCenter 是一种方便的 API,用于实现发布-订阅模式,而无需在发布服务器和订阅服务器之间直接引用。 在 .NET 10 及更高版本中,应首选以下项之一:
- 用于分离、可测试的基于消息的通信的 CommunityToolkit.Mvvm
WeakReferenceMessenger。 - 用于本地通信的常规 .NET 事件,最好是 WeakEventManager 避免内存泄漏。
迁移到 WeakReferenceMessenger
Toolkit messenger 使用强类型邮件和对收件人的弱引用。 最少的迁移如下所示:
将 CommunityToolkit.Mvvm 包添加到项目。 在项目文件中(
.csproj):<ItemGroup> <PackageReference Include="CommunityToolkit.Mvvm" Version="8.*" /> </ItemGroup>定义消息类型(可选)发送单个有效负载值时使用
ValueChangedMessage<T>):using CommunityToolkit.Mvvm.Messaging.Messages; public sealed class HiMessage : ValueChangedMessage<string> { public HiMessage(string name) : base(name) { } }从发布者发送消息:
using CommunityToolkit.Mvvm.Messaging; // Send without a direct reference to any recipients WeakReferenceMessenger.Default.Send(new HiMessage("John"));接收收件人中的邮件:
- 实现
IRecipient<TMessage>并注册信使,或 - 继承
ObservableRecipient并启用接收。
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging.Messages; public sealed class GreetingViewModel : IRecipient<HiMessage> { public GreetingViewModel() { // Register this instance to receive HiMessage notifications WeakReferenceMessenger.Default.Register(this); } public void Receive(HiMessage message) { var name = message.Value; // "John" // Handle the message (e.g., update state) } // Call this when the recipient is disposed/no longer needed public void Unregister() { WeakReferenceMessenger.Default.Unregister<HiMessage>(this); } }- 实现
映射常见的 MessagingCenter 模式
- 无有效负载发送:
MessagingCenter.Send<TSender>(sender, message)→定义空消息类型(无有效负载)和Send(new MyMessage())。 - 使用有效负载发送:
MessagingCenter.Send<TSender, TArgs>(sender, message, args)→使用ValueChangedMessage<TArgs>或具有属性的自定义消息。 - 订阅回调:
MessagingCenter.Subscribe<TSender>(subscriber, message, callback)→实现IRecipient<TMessage>和注册;方法是Receive回调。 - 取消订阅:
MessagingCenter.Unsubscribe→WeakReferenceMessenger.Default.Unregister<TMessage>(recipient)。
何时改用事件
对于简单的本地通信(例如,控件与其父级之间),标准 .NET 事件通常足够。 若要降低长期发布者内存泄漏的风险,请使用 WeakEventManager:
public class Counter
{
readonly Microsoft.Maui.WeakEventManager _weakEventManager = new();
public event EventHandler<int> CountChanged
{
add => _weakEventManager.AddEventHandler(value);
remove => _weakEventManager.RemoveEventHandler(value);
}
int _count;
public void Increment()
{
_count++;
_weakEventManager.HandleEvent(this, _count, nameof(CountChanged));
}
}
小窍门
如果已在 CommunityToolkit 中使用 MVVM, ObservableRecipient 则可以在设置时 IsActive 自动管理注册生存期。
发布-订阅模式是一种消息传送模式,发布者无需了解任何接收方(称为订阅者)即可发送消息。 同样,订阅者无需了解任何发布者即可侦听特定消息。
.NET 中的事件实现发布-订阅模式,如果不需要松散耦合(例如控件和包含它的页面),则组件之间的通信层是最简单且最简单的方法。 但是,发布服务器和订阅服务器生存期由对象相互引用耦合,订阅服务器类型必须具有对发布服务器的类型的引用。 这可以创建内存管理问题,尤其是在存在订阅静态或长生存期对象的事件的短生存期对象时。 如果未删除事件处理程序,则订阅服务器将通过对它的引用在发布服务器中保持活动状态,这将阻止或延迟订阅服务器的垃圾回收。
.NET 多平台应用 UI (.NET MAUI) MessagingCenter 类实现发布-订阅模式,允许不方便按对象和类型引用链接的组件之间基于消息的通信。 此机制允许发布者和订阅者在不相互引用的情况下进行通信,从而帮助减少它们之间的依赖关系。
重要
MessagingCenter 已弃用,建议将其 WeakReferenceMessenger 替换为 CommunityToolkit.Mvvm NuGet 包。 有关详细信息,请参阅 Messenger。
该 MessagingCenter 类提供多播发布-订阅功能。 这意味着,可以有多个发布者发布单个消息,并且可以有多个订阅者侦听同一消息:
发布者使用 MessagingCenter.Send 该方法发送消息,而订阅者使用 MessagingCenter.Subscribe 该方法侦听消息。 此外,订阅者还可以使用该方法从消息订阅取消订阅( MessagingCenter.Unsubscribe 如果需要)。
重要
在内部,类 MessagingCenter 使用弱引用。 这意味着它不会使对象保持活动状态,并允许对其进行垃圾回收。 因此,仅当类不再希望接收消息时,才应该取消订阅消息。
发布消息
MessagingCenter 消息是字符串。 发布者使用其中一个 MessagingCenter.Send 重载通知订阅者消息。 以下代码示例发布消息 Hi :
MessagingCenter.Send<MainPage>(this, "Hi");
在此示例中, Send 该方法指定表示发送方的泛型参数。 若要接收消息,订阅服务器还必须指定相同的泛型参数,指示他们正在侦听来自该发件人的消息。 此外,此示例还指定两个方法参数:
- 第一个参数指定发送方实例。
- 第二个参数指定消息。
还可以使用消息发送有效负载数据:
MessagingCenter.Send<MainPage, string>(this, "Hi", "John");
在此示例中,该方法 Send 指定两个泛型参数。 第一个是发送消息的类型,第二种是要发送的有效负载数据的类型。 若要接收消息,订阅服务器还必须指定相同的泛型参数。 这允许多个消息共享消息标识,但发送不同的有效负载数据类型,供不同的订阅者接收。 此外,此示例还指定第三个方法参数,该参数表示要发送到订阅服务器的有效负载数据。 在这种情况下,有效负载数据是一个 string。
该方法 Send 将使用火忘方法发布消息和任何有效负载数据。 因此,即使没有注册用于接收消息的订阅者,也会发送消息。 在这种情况下,将忽略已发送的消息。
订阅消息
订阅者可以使用其中一个 MessagingCenter.Subscribe 重载注册以接收消息。 下面的代码示例演示了一个示例:
MessagingCenter.Subscribe<MainPage> (this, "Hi", (sender) =>
{
// Do something whenever the "Hi" message is received
});
在此示例中,该方法 Subscribe 将 this 对象订阅类型 Hi 发送 MainPage 的消息,并执行回调委托以响应接收消息。 指定为 lambda 表达式的回调委托可以是更新 UI、保存某些数据或触发其他作的代码。
注释
订阅服务器可能不需要处理已发布消息的每个实例,这可以由方法上 Subscribe 指定的泛型类型参数控制。
以下示例演示如何订阅包含有效负载数据的消息:
MessagingCenter.Subscribe<MainPage, string>(this, "Hi", async (sender, arg) =>
{
await DisplayAlert("Message received", "arg=" + arg, "OK");
});
在此示例中,该方法 Subscribe 订阅 Hi 类型 MainPage 发送的消息,其有效负载数据是一个 string。 回调委托是在响应接收此类消息时执行的,该消息在警报中显示有效负载数据。
重要
由该方法执行的 Subscribe 委托将在使用 Send 该方法发布消息的同一线程上执行。
取消订阅邮件
订阅者可以取消订阅他们不再想要接收的消息。 这是通过其中一个重载实现的 MessagingCenter.Unsubscribe :
MessagingCenter.Unsubscribe<MainPage>(this, "Hi");
在此示例中,该方法Unsubscribe取消订阅this类型MainPage发送的消息中的Hi对象。
应使用指定两个泛型参数的 Unsubscribe 重载取消订阅包含有效负载数据的消息:
MessagingCenter.Unsubscribe<MainPage, string>(this, "Hi");
在此示例中,该方法Unsubscribe从类型发送MainPage的消息中取消订阅this对象,其有效负载数据是一个 stringHi 。