Created
July 23, 2017 21:42
-
-
Save aabs/ec936dd21a1e823fcef2e0b6e4110eb0 to your computer and use it in GitHub Desktop.
Functional IO Dependency Wrapping
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Use delegates to provide a nice clean name for complex func types | |
public delegate bool FileExists(string path); | |
public delegate byte[] ReadContent(string path); | |
public delegate void WriteContent(string path, byte[] content); | |
// this is the original function looked at, which contains two accesses of the filesystem, | |
// which had been intercepted through the use of System.IO.Abstractions | |
public byte[] GetContent(string path) | |
{ | |
if (path == null) { throw new ArgumentNullException(nameof(path)); } | |
if (!_fileSystem.File.Exists(path)) | |
{ | |
throw new FileNotFoundException(); | |
} | |
return _fileSystem.File.ReadAllBytes(path); | |
} | |
// First extract the external dependencies as functions and pass them in as args | |
public static byte[] GetContent(string path, Func<string, bool> exists, Func<string, byte[]> read) | |
{ | |
if (path == null) { throw new ArgumentNullException(nameof(path)); } | |
if (!exists(path)) | |
{ | |
throw new FileNotFoundException(); | |
} | |
return read(path); | |
} | |
// Now change the original function itself to return a functon | |
// this allows the function to be partially invoked with the dependencies and than passed in to | |
// some other client to be used. | |
// NB: Note the use of the same delegate for the result as for the arg, indicating the function acting as a kind of 'pass-through' | |
// which does capture aspects of the implementation somewhat. | |
public static ReadContent GetContent2(FileExists exists, ReadContent read) => (string path) => | |
{ | |
if (path == null) | |
{ | |
throw new ArgumentNullException(nameof(path)); | |
} | |
if (!exists(path)) | |
{ | |
throw new FileNotFoundException(); | |
} | |
return read(path); | |
}; | |
[UnitTest] | |
public static void TestCase() | |
{ | |
// just pass in a couple of dummy functions to mock the interactions with the filesystem | |
var t = GetContent2(x => true, y => new byte[] { }); | |
var result = t("blah"); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment