c# - WPF MVVM 中 ViewModel 上的 Mediatr 通知
问题描述
在实现 WPF 应用程序时,我偶然发现了我的应用程序在每个 ViewModel 中都需要一些全局数据的问题。然而,一些 ViewModel 只需要读取权限,而其他的需要对该字段的读/写权限。起初,我偶然发现了 Microsoft 的 SessionContext 理念,如下所示:
public class SessionContext
{
#region Public Members
public static string UserName { get; set; }
public static string Role { get; set; }
public static Teacher CurrentTeacher { get; set; }
public static Parent CurrentParent { get; set; }
public static LocalStudent CurrentStudent { get; set; }
public static List<LocalGrade> CurrentGrades { get; set; }
#endregion
#region Public Methods
public static void Logon(string userName, string role)
{
UserName = userName;
Role = role;
}
public static void Logoff()
{
UserName = "";
Role = "";
CurrentStudent = null;
CurrentTeacher = null;
CurrentParent = null;
}
#endregion
}
这不是(至少在我看来)可以很好地测试,并且如果我的全局数据增长它会出现问题(认为这可能发生在这个应用程序中)。我发现的下一件事是来自此链接的中介者/中介者模式的实现。我喜欢设计的理念 Norbert 会来到这里,并考虑为我的项目实施类似的东西。然而,在这个项目中,我已经在使用令人印象深刻的 Mediatr Nuget 包,这也是一个 Mediator 实现。所以我想“为什么要重新发明轮子”,如果我可以使用一个很好且经过良好测试的调解器。但这里开始了我真正的问题:如果其他 ViewModel 对全局数据的更改发送到我的只读 ViewModel,我会使用通知。这意味着:
public class ReadOnlyViewModel : NotificationHandler<Notification>
{
//some Member
//global Data
public string Username {get; private set;}
public async Task Handle(Notification notification, CancellationToken token)
{
Username = notification.Username;
}
}
现在的问题: 1. 这是使用 MVVM 的好习惯吗(只是感觉这样做是错误的,因为感觉就像在 ViewModel 中暴露业务逻辑) 2. 有没有更好的方法来分离它,以便我的 Viewmodel 不需要继承 5 到 6 个不同的 NotificationHandlers<,>?
更新: 澄清我想在这里实现的目标:我的目标是实现一个 wpf 应用程序,该应用程序为其一个窗口管理一些全局数据(比如上面提到的用户名)。这意味着因为我使用的是 DI 容器(并且因为它是什么类型的数据),所以我必须将提议的 Service @mm8 声明为单例。但是,如果(我有这种情况)我需要打开一个此时需要不同全局数据的新窗口,这有点问题。这意味着我要么需要将生命周期更改为“某种范围”之类的东西,要么(打破类的单一职责)为不同的目的添加更多字段,或者我为我可能需要的 n 个可能的 Windows 创建 n 个服务打开。对于拆分服务的第一个想法:
解决方案
您可以使用注入视图模型的共享服务。例如,它可以实现两个接口,一个用于写操作,一个用于只读操作,例如:
public interface IReadDataService
{
object Read();
}
public interface IWriteDataService : IReadDataService
{
void Write();
}
public class GlobalDataService : IReadDataService, IWriteDataService
{
public object Read()
{
throw new NotImplementedException();
}
public void Write()
{
throw new NotImplementedException();
}
}
然后,您将注入应该具有写访问权限的视图模型 a IWriteDataService
(以及其他具有 a 的IReadDataService
):
public ViewModel(IWriteDataService dataService) { ... }
该解决方案既使代码易于理解又易于测试。
推荐阅读
- mongodb - 本地与远程数据库的 Mongo DB BI 连接器
- r - 如何将训练数据中的中值估算为 R 中的测试数据?
- typescript - 在 CI/CD 管道上使用 docker 镜像和 CircleCI
- python - python中线性回归分类器的输入批处理
- html - 有什么方法可以去除网站上图片的背景?
- android - 在 IntelliJ Idea 中开发可视化 Kotlin 应用程序
- azure - 重新启动后应用于生产槽的应用服务暂存槽设置
- python - 将 sqlalchemy 查询中的值添加到 ajax 列表中
- python - 计算 TP、FP、TN、FN 值
- unity3d - Unity 如何为 AssetBundle 生成缓存哈希