C#的MVVM 工具包------Messenger
Messenger 模式是一种设计模式,它允许应用程序的不同部分之间进行松耦合的通信。在 MVVM 架构中,这种模式尤为重要,因为它可以帮助实现视图(View)和视图模型(ViewModel)之间的清晰分离。MVVM 工具包提供两种现用的实现:WeakReferenceMessenger 和 StrongReferenceMessenger,前者在内部使用弱引用,为收件人提供自动内存管理,而后者使用强引用,并要求开发人员在不再需要收件人时手动取消订阅收件人,虽然使起来稍显繁琐,但这一点换来的是提供更好的性能,而且内存使用量要少得多。
WeakReferenceMessenger
CommunityToolkit.Mvvm.Messaging命名空间下的一个实现,它使用弱引用(Weak References)来管理消息的发送者和接收者,从而避免内存泄漏并提高性能。
- 工作原理
WeakReferenceMessenger的核心工作原理基于弱引用的概念。弱引用允许一个对象被垃圾回收器回收,即使有其他对象引用它。在 WeakReferenceMessenger中,这意味着消息的发送者和接收者之间的引用是弱的,因此不会阻止它们被垃圾回收器回收。
当发送者发送消息时,WeakReferenceMessenger会将消息存储起来,并尝试找到所有注册接收该类型消息的接收者。由于使用弱引用,如果接收者被垃圾回收器回收,它将不会收到消息,从而避免了内存泄漏的风险。
- 主要特点
弱引用:使用弱引用来跟踪消息的发送者和接收者,减少内存占用和潜在的内存泄漏。
线程安全:消息的发送和接收是线程安全的,可以在多线程环境中使用。
灵活性:支持多种消息类型和通道,允许不同的模块或组件之间进行特定的通信。
解耦:发送者和接收者不需要直接引用对方,它们只需要注册到 WeakReferenceMessenger`即可。
- 使用示例
假设正在开发一个具有主界面和设置界面的应用程序。主界面允许用户更改主题设置,而设置界面监听这些更改并相应地更新界面。
定义消息类型:
public class ThemeChangedMessage
{
public string NewTheme { get; set; }
public ThemeChangedMessage(string newTheme)
{
NewTheme = newTheme;
}
}
创建消息发送者:
在主界面的 ViewModel 中,我们定义一个方法来更改主题,并发送 ThemeChangedMessage。
public class MainViewModel
{
public void ChangeTheme(string newTheme)
{
// 执行更改主题的逻辑...
// 发送主题更改消息
WeakReferenceMessenger.Default.Send(new ThemeChangedMessage(newTheme));
}
}
创建消息接收者:
在设置界面的 ViewModel 中,注册为ThemeChangedMessage的接收者,并处理消息。
public class SettingsViewModel : ObservableRecipient
{
public SettingsViewModel()
{
// 注册接收 ThemeChangedMessage
WeakReferenceMessenger.Default.Register<ThemeChangedMessage>(this, HandleThemeChanged);
}
private void HandleThemeChanged(ThemeChangedMessage message)
{
// 更新设置界面以反映新主题
// 例如,更改控件的颜色或字体
}
protected override void OnDeactivated()
{
// 取消注册消息接收,避免内存泄漏
WeakReferenceMessenger.Default.UnregisterAll(this);
}
}
处理消息:
当用户在主界面更改主题时,MainViewModel会发送一个ThemeChangedMessage。WeakReferenceMessenger会找到SettingsViewModel因为它注册了对此类消息的兴趣),并调用`HandleThemeChanged 方法来处理消息。
- 性能考虑
使用 WeakReferenceMessenger时,需要注意以下几点以确保最佳性能:
- 避免长时间持有消息接收者:如果消息接收者不再需要,应该取消注册,以允许垃圾回收器回收它。
- -合理使用消息通道:通过为不同的消息类型定义通道,可以减少消息处理的开销,并提高应用程序的响应性。
- 优化消息处理逻辑:确保消息处理逻辑尽可能高效,避免在消息处理中执行耗时的操作。
StrongReferenceMessenger
StrongReferenceMessenger提供了一种使用强引用来跟踪注册的收件人的方法。
- 工作原理
StrongReferenceMessenger是IMessenger接口的一种实现,它使用强引用来维护消息发送者和接收者之间的联系。这意味着,只要收件人没有被显式注销,它就会一直被StrongReferenceMessenger保持活动状态,即使没有其他引用指向该收件人。这种机制确保了消息能够可靠地传递给收件人,但也意味着开发者需要负责管理收件人的生命周期,以避免潜在的内存泄漏问题。
- 注册与发送消息
使用StrongReferenceMessenger时,首先需要注册消息接收者。注册可以通过两种方式进行:使用IRecipient<TMessage>接口或MessageHandler<TRecipient, TMessage>委托。
使用IRecipient<TMessage>接口:
接收者需要实现IRecipient<TMessage>接口,并提供一个Receive(TMessage)方法来处理接收到的消息。
public class MyRecipient : IRecipient<LoggedInUserChangedMessage>
{
public void Receive(LoggedInUserChangedMessage message)
{
// 处理消息...
}
}
注册和发送消息的示例:
// 注册消息接收者
StrongReferenceMessenger.Default.Register<MyRecipient, LoggedInUserChangedMessage>(myRecipient);
// 发送消息
StrongReferenceMessenger.Default.Send(new LoggedInUserChangedMessage(user));
使用MessageHandler<TRecipient, TMessage>委托:
这种方式允许你直接使用lambda表达式或方法组来作为消息处理程序。
// 注册消息处理程序
StrongReferenceMessenger.Default.Register<LoggedInUserChangedMessage>((message) => {
// 处理消息...
});
// 发送消息
StrongReferenceMessenger.Default.Send(new LoggedInUserChangedMessage(user));
- 取消注册
由于StrongReferenceMessenger使用强引用,因此当不再需要接收消息时,必须显式取消注册收件人或处理程序。这可以通过以下几种方式完成:按消息类型取消注册
// 取消注册特定类型的消息
StrongReferenceMessenger.Default.Unregister<LoggedInUserChangedMessage>(myRecipient);
按消息类型和通道取消注册
// 取消注册特定通道的特定类型消息
StrongReferenceMessenger.Default.Unregister<LoggedInUserChangedMessage, int>(myRecipient, channelToken);
取消注册所有消息
// 取消注册所有消息,适用于所有通道
StrongReferenceMessenger.Default.UnregisterAll(myRecipient);
- 应用示例
假设正在开发一个具有用户登录功能的应用程序。当用户登录成功后,我们需要更新应用程序的不同部分,例如更新用户信息显示、加载新的用户配置文件图像等。我们可以使用StrongReferenceMessenger来实现这一跨组件通信的需求。
定义消息类型:
public class LoggedInUserChangedMessage : ValueChangedMessage<User>
{
public LoggedInUserChangedMessage(User user) : base(user)
{
}
}
注册消息接收者:
public class UserViewModel
{
public UserViewModel()
{
// 注册登录消息
StrongReferenceMessenger.Default.Register<LoggedInUserChangedMessage>(this, (r, m) =>
{
// 更新用户信息
this.CurrentUser = m.NewValue;
});
}
}
发送消息:
public class LoginViewModel
{
public async Task LoginAsync(string username, string password)
{
// 假设这里有验证用户凭据的逻辑
User user = ValidateCredentials(username, password);
// 用户登录成功,发送登录消息
StrongReferenceMessenger.Default.Send(new LoggedInUserChangedMessage(user));
}
}
处理消息:
public class UserProfileViewModel : IRecipient<LoggedInUserChangedMessage>
{
public void Receive(LoggedInUserChangedMessage message)
{
// 更新用户的配置文件图像
this.UserProfileImage = message.NewValue.AvatarUrl;
}
}
总结
Messenger是.NET社区CommunityToolkit.Mvvm工具包中提供的一种消息传递机制,它允许应用程序中的不同组件之间进行松耦合的通信,而无需直接引用对方,降低了组件之间的依赖性,提高代码的可维护性和灵活性。在 MVVM 架构中,这种模式尤其有用,它支持视图和视图模型之间的清晰分离,提高应用程序的性能和可维护性,同时保持了它们之间通信的流畅和高效。
Messenger作为一个强大且灵活的消息传递解决方案,将有助于构建更加健壮和可扩展的应用程序。