是否向ViewModel添加扩展方法维护ViewModel规则?

时间:2015-05-26 22:13:08

标签: c# wpf database mvvm viewmodel

我的ViewModel中有一些访问数据库连接的方法。我知道这是不正确的,因为ViewModel不应该负责连接数据库。

作为解决方案,我将一些方法移动到另一个类作为扩展方法。即

Public static void (this MainViewModel viewModel){
viewModel.Textbox = "hello";
viewModel.Tables = GetDatabaseConnectionAndReturnTables();
//...//
}

这真的是一种从viewmodel中获取数据库连接功能的方法吗?这是我能想到的唯一解决方案。

谢谢,

3 个答案:

答案 0 :(得分:3)

  

这是否真的是一种获取数据库连接功能的方法   viewmodel?

简答:不。

不是那么长的答案:扩展方法是为了在源代码不可用时向类型添加方法,你不能派生一个类,或者你想将它们添加到结构中(struct aren&#39 ; t可继承......)。

实际上,您正在为视图模型添加方法,就像它们被添加为直接类成员一样。如果将它们实现为视图模型实例成员或使用扩展方法,则可以在视图模型中实现方法。

如果要从视图模型中有效地抽象数据,您应该检查一些设计模式,如:

很难为您提供有关如何在Q&amp; A格式中实现真正的关注点分离的更多指导(我需要在这里写一本书),但我会开始更多地了解这些设计模式。< / p>

另外,我会看一下域驱动设计的内容。

答案 1 :(得分:1)

走这条路可能会变得很古怪。如果在扩展方法和嵌套视图模型中的函数之间做出选择,那么后者将是首选。

然而...... 两者都是非常糟糕的做法。您应该阅读DAORepository设计模式。使用DAO模式隐藏数据库的详细信息,仅显示persistence图层的知识。然后使用Repository模式,您可以使用允许您操作特定数据集的方法,而无需关心如何检索和/或存储数据。

然后使用dependency injection将存储库注入到使用该数据执行特定任务的模型中。然后,您可以将该模型传递到视图模型中,该模型只显示模型中可用的信息。

答案 2 :(得分:0)

将数据访问权限保留在MVVM中的视图模型之外的一个重要原因是帮助进行测试。使用MVVM的一个巨大优势是可以使更多代码可测试,而不依赖于View。通过使视图模型调用扩展方法,您无法抽象出数据存储调用。这意味着在进行单元测试时,必须始终在数据库中包含数据,以便进行查询。这也意味着您的数据库将填满在运行单元测试时插入的一堆垃圾数据。您希望在编写集成测试时访问数据库,但实际上并不是在测试视图模型的功能时。

将数据访问抽象到隐藏在接口后面的服务或存储库中,可以测试代码,而无需处理与数据库的连接。您可以创建fakesmocks

这样,您的代码就可以执行此操作:

private IMyRepository repository;
public MainWindowViewModel(IMyRepository repo)
{
    this.repository = repo;
}

public Task SaveObject(MyObject obj)
{
    return this.repository.Save(obj);
}

当您进行单元测试时,您只需向视图模型构造函数提供模拟或伪造,然后让它在save方法上点击。

您使用扩展方法仍然意味着您与数据层紧密耦合。它可能被抽象到一个不同的文件中,但由于您无法重写数据访问而无需重写原始扩展方法,您的视图模型仍然紧密耦合。

这样做的另一个好处是,如果需要查询数据,其他视图模型可能会使用相同的方法。这节省了必须复制和将代码粘贴到可能需要它的每个视图模型的扩展方法或创建视图模型的实例,只是为了访问其扩展方法来获取数据。视图模型通常仅限于一个视图,但它们提供的数据可用于 n 视图。