C#的MVVM 工具包——Messenger

C#的MVVM 工具包——Messenger

Messenger 模式是一种设计模式,它允许应用程序的不同部分之间进行松耦合的通信。在 MVVM 架构中,这种模式尤为重要,因为它可以帮助实现视图(View)和视图模型(ViewModel)之间的清晰分离。MVVM 工具包提供两种现用的实现:WeakReferenceMessenger 和 StrongReferenceMessenger,前者在内部使用弱引用,为收件人提供自动内存管理,而后者使用强引用,并要求开发人员在不再需要收件人时手动取消订阅收件人,虽然使起来稍显繁琐,但这一点换来的是提供更好的性能,而且内存使用量要少得多。


WeakReferenceMessenger


CommunityToolkit.Mvvm.Messaging命名空间下的一个实现,它使用弱引用(Weak References)来管理消息的发送者和接收者,从而避免内存泄漏并提高性能。

  1. 工作原理

WeakReferenceMessenger的核心工作原理基于弱引用的概念。弱引用允许一个对象被垃圾回收器回收,即使有其他对象引用它。在 WeakReferenceMessenger中,这意味着消息的发送者和接收者之间的引用是弱的,因此不会阻止它们被垃圾回收器回收。

当发送者发送消息时,WeakReferenceMessenger会将消息存储起来,并尝试找到所有注册接收该类型消息的接收者。由于使用弱引用,如果接收者被垃圾回收器回收,它将不会收到消息,从而避免了内存泄漏的风险。

  1. 主要特点

弱引用:使用弱引用来跟踪消息的发送者和接收者,减少内存占用和潜在的内存泄漏。

线程安全:消息的发送和接收是线程安全的,可以在多线程环境中使用。

灵活性:支持多种消息类型和通道,允许不同的模块或组件之间进行特定的通信。

解耦:发送者和接收者不需要直接引用对方,它们只需要注册到 WeakReferenceMessenger`即可。

  1. 使用示例

假设正在开发一个具有主界面和设置界面的应用程序。主界面允许用户更改主题设置,而设置界面监听这些更改并相应地更新界面。

定义消息类型:

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 方法来处理消息。

  1. 性能考虑

使用 WeakReferenceMessenger时,需要注意以下几点以确保最佳性能:

  • 避免长时间持有消息接收者:如果消息接收者不再需要,应该取消注册,以允许垃圾回收器回收它。
  • -合理使用消息通道:通过为不同的消息类型定义通道,可以减少消息处理的开销,并提高应用程序的响应性。
  • 优化消息处理逻辑:确保消息处理逻辑尽可能高效,避免在消息处理中执行耗时的操作。

StrongReferenceMessenger

StrongReferenceMessenger提供了一种使用强引用来跟踪注册的收件人的方法。

  1. 工作原理

StrongReferenceMessenger是IMessenger接口的一种实现,它使用强引用来维护消息发送者和接收者之间的联系。这意味着,只要收件人没有被显式注销,它就会一直被StrongReferenceMessenger保持活动状态,即使没有其他引用指向该收件人。这种机制确保了消息能够可靠地传递给收件人,但也意味着开发者需要负责管理收件人的生命周期,以避免潜在的内存泄漏问题。

  1. 注册与发送消息

使用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));
  1. 取消注册

由于StrongReferenceMessenger使用强引用,因此当不再需要接收消息时,必须显式取消注册收件人或处理程序。这可以通过以下几种方式完成:按消息类型取消注册

// 取消注册特定类型的消息
StrongReferenceMessenger.Default.Unregister<LoggedInUserChangedMessage>(myRecipient);

按消息类型和通道取消注册

// 取消注册特定通道的特定类型消息
StrongReferenceMessenger.Default.Unregister<LoggedInUserChangedMessage, int>(myRecipient, channelToken);

取消注册所有消息

// 取消注册所有消息,适用于所有通道
StrongReferenceMessenger.Default.UnregisterAll(myRecipient);
  1. 应用示例

假设正在开发一个具有用户登录功能的应用程序。当用户登录成功后,我们需要更新应用程序的不同部分,例如更新用户信息显示、加载新的用户配置文件图像等。我们可以使用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作为一个强大且灵活的消息传递解决方案,将有助于构建更加健壮和可扩展的应用程序。

  • 0
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C# MVVM(Model-View-ViewModel)是一种软件架构模式,用于将用户界面(View)与业务逻辑(ViewModel)分离,并通过数据绑定实现它们之间的通信。MVVM可用于任何C#应用程序,包括桌面应用程序、移动应用程序和Web应用程序。 如果你想了解关于C# MVVM的示例代码,我可以提供一个简单的MVVM示例: 在这个示例中,我们假设你已经安装了Visual Studio,并创建了一个名为"MVVMDemo"的C#项目。 1. 创建一个名为"Models"的文件夹,并在其中创建一个名为"Person.cs"的类文件。此类将包含有关个人的属性和方法。例如: ``` using System.ComponentModel; namespace MVVMDemo.Models { public class Person : INotifyPropertyChanged { private string name; public string Name { get { return name; } set { name = value; OnPropertyChanged("Name"); } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } } ``` 2. 创建一个名为"ViewModels"的文件夹,并在其中创建一个名为"MainViewModel.cs"的类文件。此类将包含与用户界面交互的逻辑。例如: ``` using MVVMDemo.Models; namespace MVVMDemo.ViewModels { public class MainViewModel { private Person person; public MainViewModel() { person = new Person(); } public Person Person { get { return person; } set { person = value; } } } } ``` 3. 创建一个名为"Views"的文件夹,并在其中创建一个名为"MainWindow.xaml"的XAML文件。此文件将包含用户界面的设计和布局。例如: ```xml <Window x:Class="MVVMDemo.Views.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:MVVMDemo.ViewModels" Title="MVVM Demo" Height="350" Width="500"> <Window.DataContext> <local:MainViewModel/> </Window.DataContext> <Grid> <TextBlock Text="Name:"/> <TextBox Text="{Binding Person.Name, Mode=TwoWay}"/> <TextBlock Text="{Binding Person.Name}"/> </Grid> </Window> ``` 在此示例中,我们创建了一个MainWindow窗口,其中包含一个TextBlock、一个TextBox和另一个TextBlock。第一个TextBlock显示"Name:",TextBox用于输入姓名,第二个TextBlock通过数据绑定显示所输入的姓名。 这只是一个简单的C# MVVM示例,更复杂的应用程序可能会涉及更多的模型、视图和视图模型。希望这个示例可以帮助你开始使用C# MVVM。如果你有更多问题,请随时提问!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值