views:

308

answers:

4

System.IO.Path in .NET is notoriously clumsy to work with. In my various projects I keep encountering the same usage scenarios which require repetitive, verbose and thus error-prone code snippets that use Path.Combine, Path.GetFileName, Path.GetDirectoryName, String.Format, etc. Scenarios like:

  • changing the extension for a given file name
  • changing the directory path for a given file name
  • building a file path using string formatting (like "Package{0}.zip")
  • building a path without resorting to using hard-coded directory delimiters like \ (since they don't work on Linux on Mono)
  • etc etc

Before starting to write my own PathBuilder class or something similar: is there a good (and proven) open-source implementation of such a thing in C#?

UPDATE: OK, just an illustration of what I mean:

        string zipFileName = Path.GetFileNameWithoutExtension(directoryName) + ".zip";
        zipFileName = Path.Combine(
            Path.GetDirectoryName(directoryName), 
            zipFileName);

A nicer fluent API could look like this:

Path2 directoryName = "something";
Path2 zipFileName = directoryName.Extension("zip");

Or when building a path:

Path2 directoryName = "something";
Path2 directory2 = directoryName.Add("subdirectory")
    .Add("Temp").Add("myzip.zip");

instead of

string directory2 = Path.Combine(Path.Combine(Path.Combine(
     directoryName, "subdirectory"), "Temp"), "myzip.zip");

I actually did implement something like this in the past, but in a separate project. I've decided now to reuse it as a standalone C# class added "as link" in VisualStudio in my other projects. It's not a cleanest solution, but I guess it will do. If you're interested, you can see the code here.

+2  A: 

You should take a look at the enhancements to Path in v4 of the framework first.

For example, Path.Combine will now accept multiple path fragments, rather than having to nest them.

Rowland Shaw
Nice, but I'm looking for something that will work for the existing code base (at least 3.5).
Igor Brejc
+3  A: 

System.IO.Path already covers the following from your list:

  • changing the extension for a given file name
  • changing the directory path for a given file name
  • building a path without resorting to using hard-coded directory delimiters like \ (since they don't work on Linux on Mono)

And you can easily create a class or some extensions methods to do the remaining, based on the Path class.

Henk Holterman
I didn't say it wasn't possible. I'm just saying that the API could be much better.
Igor Brejc
I'm with Henk here. The existing API is pretty good. Reshape it with extension methods if you want it to look different, but e.g. your example above doesn't use the already present Path.ChangeExtension method. I'd have a look for better ways to do what you're trying to do with the API you have before looking at changing API.
Iain Galloway
Iain, it's not as if I haven't used it for some 5-6 years now :). So I guess after such a long time I can have an opinion that it's _not_ pretty good. But I guess that's a matter of taste.But i recommend taking a look at APIs for things like Windsor Castle, FluentNHibernate, AutoMapper and similar.
Igor Brejc
Another example of why I think it's not a good API. Let's say you have a path to a directory. How do you get the parent path? You call GetDirectoryName(). Bad naming, in my opinion. First of all, I already _have_ a directory, so what does this method give me (if I'm a newbie and I don't know). Second, you get the _whole_ path, not just the name of the directory. It's such little things that make an API good or bad. The guys who did System.IO.Path should have taken a look at Microsoft's own design guidelines: http://msdn.microsoft.com/en-us/library/ms229042.aspx
Igor Brejc
+1  A: 

FluentPath looks nice and neat.

schrodinger's code
Yes, something in this direction, although FluentPath is more ambitious, it wraps IO file system operations too.
Igor Brejc
+2  A: 

You might also want to checkout the "NDepend.Helpers.FileDirectoryPath" library.

Christian.K
Cool, this looks like something pretty good. Thanks.
Igor Brejc