MVVM/IoC 我应该包装每个 IO 操作吗?

Posted

技术标签:

【中文标题】MVVM/IoC 我应该包装每个 IO 操作吗?【英文标题】:MVVM/IoC Should I Wrap Every IO Operation? 【发布时间】:2019-06-04 03:54:57 【问题描述】:

在遵循 IoC 标准的 C# 代码中,是否应该将每个 IO 操作都包装在处理 IO 操作的类中?例如,我到处都在使用 File.Exists 和 Directory.Create —— 我是否应该有一个类公开这两个函数以及整个应用程序使用的每个文件操作,以创建一个抽象层?

Path.Combine 或 Path.DirectorySeparatorChar 怎么样,我可以直接使用它还是应该围绕它们创建包装器?

返回文件信息变得有点棘手,我可以有一个函数来返回文件大小,但是如果我需要访问几个属性,那么我返回 FileInfo 对象——我不应该只是在代码中初始化 FileInfo而不是包装它?

【问题讨论】:

【参考方案1】:

找到答案了。

不包装 IO 调用意味着您无法对类进行单元测试,因为它会更改真实文件而不是在沙箱中运行。

这意味着,是的,每个呼叫都必须被包装。幸运的是,System.IO.Abstraction 提供了这样的抽象,所以只需将其插入项目并使用它。

然后我可以创建 IFileSystemExt 来公开一组常见的 IO 操作,例如“确保路径的文件夹存在”和“如果存在则删除文件”。

【讨论】:

【参考方案2】:

在依赖注入 (DI) 的上下文中,不能也不应该普遍说明必须做什么和不可以做什么。这实际上取决于尝试解决的问题类型。如果唯一关心的是可测试性,那么隐藏任何不确定或具有副作用的内容可能是可取的。

但请注意,这不包括 Path.CombinePath.DirectorySeparatorChar。 IIRC,这些成员是完全确定的;当您调用它们时,它们不会访问文件系统。

然而,一种常见的 DI 方法是应用 Dependency Inversion Principle (DIP)。根据这个原则,客户端代码决定和控制它使用的多态 API 的形状。一旦客户端代码清除了它需要的接口,你就去弄清楚如何实现这些接口。

许多人试图用System.IO.Abstractions 之类的东西来解决针对Windows 文件系统的可测试性问题,但这完全违反了DIP。它不是让客户端定义接口的形状,而是让实现定义 API。这是一个leaky abstraction,如果它是一个抽象的话。

【讨论】:

以上是关于MVVM/IoC 我应该包装每个 IO 操作吗?的主要内容,如果未能解决你的问题,请参考以下文章

面试官:IO 操作必须要手动关闭吗?关闭流方法是否有顺序?

我应该用链接包装标题吗? [复制]

您可以使用 Stylus、Jade 和 Coffeescript 与 Trigger.io 等原生移动包装器一起进行开发吗?

scipy学习之——io操作及其misc操作对图片的处理

Express 和 async/await:我应该用 try/catch 包装吗?

Flutter - 我可以用 Hero 包装每个小部件来为它们设置动画吗