在遵循IoC标准的C#代码中,是否应将每个IO操作包装在处理IO操作的类中?例如,我在各处使用File.Exists和Directory.Create-我是否应该有一个类公开这两个函数以及整个应用程序使用的每个文件操作来创建抽象层?
关于Path.Combine或Path.DirectorySeparatorChar,我可以直接使用它吗?还是应该在它们周围创建包装器?
返回文件信息变得有些棘手,我可以使用一个函数来返回文件大小,但是如果我需要访问几个属性,那么我将返回FileInfo对象-我不应该只是在代码中初始化FileInfo而不是包裹它?
答案 0 :(得分:0)
找到答案。
不包装IO调用意味着您无法对类进行单元测试,因为它会更改实际文件,而不是在沙箱中运行。
这意味着,是的,每个呼叫都必须包装。幸运的是,System.IO.Abstraction提供了这种抽象,因此只需将其插入到项目中并使用它即可。
然后,我可以创建IFileSystemExt来公开常用的IO操作集,例如“确保路径的文件夹存在”和“如果存在则删除文件”。
答案 1 :(得分:0)
在依赖注入(DI)的上下文中,一个不能也不应普遍声明必须做什么和不应该做什么。这实际上取决于尝试解决的问题类型。如果仅考虑可测试性,则最好隐藏任何不确定的或有副作用的东西。
不过请注意,其中不包括Path.Combine
或Path.DirectorySeparatorChar
。 IIRC,这些成员完全是确定性的;当您调用它们时,它们不会访问文件系统。
但是,DI的常见方法是应用Dependency Inversion Principle(DIP)。根据此原理,客户端代码决定并控制其使用的多态API的形状。客户端代码清除了所需的接口后,您便可以弄清楚如何实现这些接口。
许多人试图使用System.IO.Abstractions之类的东西来解决针对Windows文件系统的可测试性,但这完全违反了DIP。与其让客户端定义接口的形状,不如让实现定义API。如果完全是抽象,则为leaky abstraction。