Exposing .NET's internal StorageRoot via Reflection for accessing file/stream-based Structured Storage .NET tantalizingly exposes StorageInfo and StreamInfo as public classes, but hides the seminal StorageRoot as an internal class, leaving the user no way of creating or opening a Structured Storage from a file or stream.

Microsoft's Reference Source details the source behind StorageRoot which inherits from StorageInfo, so rather than copy the code, I've chosen to expose the static methods of StorageRoot via reflection, so that I can get a reference to the root storage of a File or Stream. I've also exposed a Close method to close an open root StorageInfo.

using System;
using System.IO;
using System.IO.Packaging;
using System.Reflection;

namespace StructuredStoreageTest
{
    public static class StorageRoot
    {
        public static StorageInfo CreateOnStream(Stream baseStream)
        {
            return (StorageInfo)InvokeStorageRootMethod(null, "CreateOnStream", baseStream);
        }

        public static StorageInfo CreateOnStream(Stream baseStream, FileMode mode)
        {
            return (StorageInfo)InvokeStorageRootMethod(null, "CreateOnStream", baseStream, mode);
        }

        public static StorageInfo Open(string path)
        {
            return (StorageInfo)InvokeStorageRootMethod(null, "Open", path);
        }

        public static StorageInfo Open(string path, FileMode mode)
        {
            return (StorageInfo)InvokeStorageRootMethod(null, "Open", path, mode);
        }

        public static StorageInfo Open(string path, FileMode mode, FileAccess access)
        {
            return (StorageInfo)InvokeStorageRootMethod(null, "Open", path, mode, access);
        }

        public static StorageInfo Open(string path, FileMode mode, FileAccess access, FileShare share)
        {
            return (StorageInfo)InvokeStorageRootMethod(null, "Open", path, mode, access, share);
        }

        public static StorageInfo Open(string path, FileMode mode, FileAccess access, FileShare share, int sectorSize)
        {
            return (StorageInfo)InvokeStorageRootMethod(null, "Open", path, mode, access, share, sectorSize);
        }

        public static void Close(StorageInfo storageRoot)
        {
            InvokeStorageRootMethod(storageRoot, "Close");
        }

        private static object InvokeStorageRootMethod(StorageInfo storageRoot, string methodName, params object[] methodArgs)
        {
            Type storageRootType = typeof(StorageInfo).Assembly.GetType("System.IO.Packaging.StorageRoot", true, false);
            return storageRootType.InvokeMember(methodName,
                BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | 
                BindingFlags.NonPublic | BindingFlags.InvokeMethod,
                null, storageRoot, methodArgs);
        }
    }
}


I can then use StorageRoot as follows:

MemoryStream myStream = new MemoryStream(streamBytes);
StorageInfo myRoot = StorageRoot.CreateOnStream(myStream);

StreamInfo dataStreamInfo = myRoot.GetStreamInfo("data");
Stream dataStream = dataStreamInfo.GetStream();
//read/process the stream
dataStream.Dispose();

StorageRoot.Close(myRoot);


Is relying upon Reflection the best alternative here? I could reproduce the StorageRoot code from Reference Source, and make StorageRoot an instance class, I suppose.
A stream-like class that doesn't implement IDisposable and needs to be closed manually, and worked with static methods, breaks POLA/POLS.

I would expect to be able to do this:

using(var ms = new MemoryStream(bytes))
using(var root = new StorageRoot(ms))
{
    // do stuff
}


I like the reflection idea to access these otherwise hidden gems, however in a code base that uses objects in a standard/idiomatic way, I see this one sticking out like a sore thumb.

I'd definitely do whatever it takes to make it work with a proper instance.