views:

346

answers:

4

As many of you know, the System.IO namespace is abysmally designed. I would like a free library that wraps the file IO functionality in a sane way (read: doesn't require you passing strings all over the place). I remember reading some time ago that there is a small handful of these libraries already written (and the author was surprised that there were not more). I think it was one of the guys on devlicious or codebetter or Los Techies that did one of them.

Does anyone know what I'm talking about or another good File IO wrapper?

Edit: I suppose I should specify that I do Test Driven Development and my concerns are largely (but not entirely) around System.IO's test friendliness.

+4  A: 

What's wrong with System.IO.FileInfo?


I was curious, so started to create a set of wrappers using ReSharper. It took me 16 minutes, and I haven't tested it, and don't know if it meets your needs. Still, I thought I'd outline the process I used:

  1. Create a new class library project
  2. Make Class1 public and rename it to be FileSystemInfoWrapper
  3. Give it a private field _fsi of type FileSystemInfo (resolve the class to get the namespace imported)
  4. Click the field and choose to Initialize in Constructor
  5. Click the field again and use ReSharper -> Code -> Generate (Alt+Ins); Choose Generate Delegating Members; Click "Public" to get all public members
  6. Same for FileInfo, but also derive from FileSystemInfoWrapper and remove the duplicate members (ReSharper could have done better here)
  7. Same for DirectoryInfo, but also derive from FileSystemInfoWrapper and fix duplicates
  8. For each of the wrappers, click the class then use ReSharper->Refactor->Extract Interface
  9. Have IFileInfoWrapper and IDirectoryInfoWrapper derive from IFileSystemInfoWrapper, and remove duplicates.

The result is interfaces that include the methods and properties of the corresponding classes, and concrete classes that delegate to the original classes and implement the interfaces. You should then be able to create your own mock classes, and change your code to use the interfaces instead of directly using the System.IO concrete classes.

John Saunders
Suppose I have a class that does something to all files in a directory. How do I test this? I can pass in a DirectoryInfo object but how do I mock it? How do I stub out the list of FileInfo objects that it will provide? How will I ensure the test doesn't actually interact with the file system?
George Mauer
Absolutely, I can of course create my own wrappers, but I know that people have already done that work, optimized it, found the bugs, etc. That was my question.
George Mauer
@George: Does your code do something to the directory, or to all of the FILES? In that case, wouldn't it make more sense from a scalability and reusability perspective to pass in either an array of FileInfo's or strings, rather than a particular directory?
Adam Robinson
+2  A: 

I'm curious what's so abysmal about the design of the System.IO namespace. Granted, choosing a particular interface or class can be somewhat of an arbitrary exercise, but I'm not familiar with the problem of having to pass strings around all over the place.

Perhaps you could give some more information about your particular issue?


EDIT

You seem to indicate that you want classes that build upon the System.IO namespace that will allow you to test without writing to the file system. I'm not seeing how you can adequately test a function that writes to the file system without it, well, writing to the file system. If you want to test your logic from a writing perspective, then allow you functions to take System.IO.Stream or System.IO.TextWriter, whichever is more appropriate. This will allow you to test the various components of your code without necessarily having any outside impact; just pass a System.IO.MemoryStream instead of a System.IO.FileStream. Obviously you won't run into issues like running out of space, access denied, etc., but you can't ever encounter those errors without running live against the file system. That's why you can expose outer functions that take System.IO.FileInfo or a string path (or an array/IEnumerable<> of either, whatever you need) that can provide another level of testing that's live.

The System.IO namespace is pretty well populated, and I've never run into a particularly non-OO approach being used.

Adam Robinson
I like to do TDD. Which means I need something a bit more than static classes and methods. But as far as passing strings around, consider Directory.GetFiles() which takes a directory as a string and returns files as a string array. For more se my responset o John
George Mauer
Then why not DirectoryInfo and FileInfo? Those are both types that bring an OO-paradigm to file management. At some point you're going to have to deal with strings when you're talking about paths. I'm not really seeing any advantage to the NDepends library that you linked to. Am I missing what you're looking for?
Adam Robinson
+3  A: 

I think you're looking for this question and this blog post. I've only wrapped System.IO.File and System.IO.Directory though. No FileInfo or other stuff.

Mauricio Scheffer
Thanks mauricio. That's not exactly what I was looking (I mean it is not the exact article) but I might end up using it rather than try to dig through codebetter to find what it was.
George Mauer
+1  A: 

Ok, I went digging. This is the article I was referring to.

And this is the API (spawned from the ndepend project

George Mauer