Search code examples
vb.netinheritanceaccess-levelssystem.io.fileinfo

"Best" way to access IO.FileInfo Protected property (OriginalPath)?


I'm working on a series of methods that will test a given path to determine if it is (or, at least could be) valid. I have a couple of overloads that will accept either an IO.FileInfo object or an IO.DirectoryInfo object - which I'd personally prefer to use to help in catching invalid characters as soon as possible in the process. One piece of information I "need" to get as a part of the process is basically the original value the user presented - especially in the case of an IO.FileInfo or IO.DirectoryInfo object as those will automatically prepend the Environment.CurrentDirectory value to any string it determines to be a relative path.

For example:

Dim TestFile As New IO.FileInfo("Testing\This is a test")

Instantiates an IO.FileInfo object with the following properties (among others):

  • DirectoryName - "C:\Development\My Solution\My Project\bin\Debug\Testing"
  • Exists - False
  • Extension - ""
  • FullName - "C:\Development\My Solution\My Project\bin\Debug\Testing\This is a test"
  • Name - "This is a test"
  • OriginalPath - "Testing\This is a test"

This last property is the one I'm most interested in. It's a Protected property of the IO.FileInfo class, which is inherited from the IO.FileSystemInfo class, but it seems to be the best possible way to retrieve the original value passed to the IO.FileInfo constructor. Obviously, I can't access the property directly with a simple Dim TestPath As String = TestFile.OriginalPath - the IDE gives shows the error "'System.IO.FileSystemInfo.OriginalPath' is not accessible in this context because it is 'Protected'" - so I can only think of one way to get this specific piece of information: Create a whole new class that inherits IO.FileSystemInfo with a Public property for the OriginalPath that reads from the base class.

PLEASE NOTE: I do have an overloading method that accepts a String value, but I was actually thinking of trying to "hide" that one behind a Private modifier so that only FileInfo and DirectoryInfo objects could be used to call this method. My primary reasoning there is that, if a FileInfo or DirectoryInfo object fails to instantiate due to invalid characters in the string (or any other reason), there's no reason for me to make the call to this method and I may be able to "clean up" the code a little.

Regardless, the creation of a whole separate class that's really only going to be used to access this one property in this one specific scenario seems like an awful lot of overhead for what should (or, at least could) be a fairly simple thing. Unfortunately, I can't think of any other way to extract that information and I'm just wondering if I may be over-thinking this.

In the meantime, I've gone ahead and created a TempFileInfo class for testing (NOTE: I haven't actually tested it yet) without explicitly implementing any "custom" code for any of the regular Public properties (required when inheriting from the IO.FileSystemInfo class):

Private Class TempFileInfo
    Inherits IO.FileSystemInfo

    Public Overrides ReadOnly Property Name As String
        Get
            Throw New NotImplementedException()
        End Get
    End Property

    Public Overrides ReadOnly Property Exists As Boolean
        Get
            Throw New NotImplementedException()
        End Get
    End Property

    Public Overrides Sub Delete()
        Throw New NotImplementedException()
    End Sub

    Public Shadows ReadOnly Property OriginalPath As String
        Get
            Return MyBase.OriginalPath
        End Get
    End Property

    Public Shared Widening Operator CType(v As FileInfo) As TempFileInfo
        Dim FSI As FileSystemInfo = v

        Return CType(FSI, TempFileInfo)
    End Operator
End Class

You'll note that I also included a Widening Operator that should allow me to convert from a "regular" IO.FileInfo object to my TempFileInfo object so that I can access my "custom" OriginalPath property. This is the only way I've found so far to "get there from here", but I wanted to go ahead and ask here in case there are other suggestions or things I might be overlooking.

The only "saving grace" for this method of implementation is that, because the "custom" TempFileInfo, the standard IO.FileInfo, and the standard IO.DirectoryInfo classes all inherit from the IO.FileSystemInfo class, I should be able to simply create an overloaded Widening Operator method for converting both IO.FileInfo objects as well as IO.DirectoryInfo objects instead of having to create a separate TempDirInfo class.


Solution

  • The path entered when a FileInfo or DirectoryInfo object is created is stored in the protected String OriginalPath field - which is used for serialization purposes - and the internal DisplayPath property, which is used as an internal reference.

    When the class object is initialized (see the Init() method in the .Net source code), the path entered is stored in both the OriginalPath Field and the DisplayPath Property.

    Both classes don't provide a public property to retrieve the initial path used to create the object.
    They both, instead, return the DisplayPath property value as an override to the ToString() method:

    Dim fInfo = New FileInfo("\SomePath\SomeFileName.ext")
    Dim originalPath = fInfo.ToString()
    

    var fInfo = new FileInfo(@"\SomePath\SomeFileName.ext");
    string originalPath = fInfo.ToString();