Last active
January 20, 2016 21:23
-
-
Save mexx/aef547bdc4f07663fe1b to your computer and use it in GitHub Desktop.
OWIN file system for `BuildAction = Resource` typed resouces
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
namespace Mexx.Owin | |
open System | |
open System.Collections.Generic | |
open System.IO | |
open System.Reflection | |
open System.Resources | |
open Microsoft.Owin.FileSystems | |
/// <summary> | |
/// Looks up files using global resources in the specified assembly. | |
/// This file system is case insensitive. | |
/// </summary> | |
type GlobalResourceFileSystem(assembly: Assembly, resourceName: string, baseNamespace: string) = | |
let lastModified = lazy (FileInfo(assembly.Location).LastWriteTimeUtc) | |
let createResourceSet resourceName = | |
new ResourceSet(assembly.GetManifestResourceStream resourceName) | |
let createStreamFor resourceName fileName () = | |
use resourceSet = createResourceSet resourceName | |
resourceSet.GetObject(fileName, true) :?> UnmanagedMemoryStream :> Stream | |
let resourceName = sprintf "%s.g.resources" resourceName | |
let createFileInfo fileName = | |
let createReadStream = createStreamFor resourceName (baseNamespace + fileName) | |
let mutable length = None | |
{ new IFileInfo with | |
member __.CreateReadStream(): Stream = | |
let result = createReadStream() | |
length <- Some result.Length | |
result | |
member __.IsDirectory: bool = false | |
member __.LastModified: DateTime = lastModified.Force() | |
member __.Length: int64 = | |
match length with | |
| None -> | |
use stream = createReadStream() | |
length <- Some stream.Length | |
length | |
| x -> x | |
|> Option.get | |
member __.Name: string = fileName | |
member __.PhysicalPath: string = null } | |
let resourceAvailable = lazy( | |
resourceName | |
|> assembly.GetManifestResourceInfo | |
|> Option.ofObj) | |
let enumerateContents = lazy( | |
use resourceSet = createResourceSet resourceName | |
resourceSet.GetEnumerator() | |
|> Seq.unfold (fun e -> if e.MoveNext() then Some(e.Key :?> string, e) else None) | |
|> Seq.where (fun x -> x.StartsWith(baseNamespace)) | |
|> Seq.map (fun x -> x.Substring(baseNamespace.Length)) | |
|> Seq.toList) | |
interface IFileSystem with | |
/// <summary> | |
/// Enumerate a directory at the given path, if any. | |
/// This file system uses a flat directory structure. Everything under the base namespace is considered to be one directory. | |
/// </summary> | |
/// <param name="subpath">The path that identifies the directory</param> | |
/// <param name="contents">The contents if any</param> | |
/// <returns>True if a directory was located at the given path</returns> | |
member __.TryGetDirectoryContents(subpath: string, contents: byref<IEnumerable<IFileInfo>>): bool = | |
let result = | |
resourceAvailable.Force() | |
|> Option.bind (fun _ -> if String.IsNullOrEmpty(subpath) || subpath <> "/" then None else subpath |> Some) | |
|> Option.map (fun _ -> enumerateContents.Force() |> List.map createFileInfo) | |
match result with | |
| None -> | |
contents <- null | |
false | |
| Some list -> | |
contents <- list | |
true | |
/// <summary> | |
/// Locate a file at the given path | |
/// </summary> | |
/// <param name="subpath">The path that identifies the file</param> | |
/// <param name="fileInfo">The discovered file if any</param> | |
/// <returns>True if a file was located at the given path</returns> | |
member __.TryGetFileInfo(subpath: string, fileInfo: byref<IFileInfo>): bool = | |
let result = | |
resourceAvailable.Force() | |
|> Option.bind (fun _ -> if String.IsNullOrEmpty(subpath) || subpath.[0] <> '/' then None else subpath |> Some) | |
|> Option.map createFileInfo | |
match result with | |
| None -> | |
fileInfo <- null | |
false | |
| Some file -> | |
fileInfo <- file | |
true |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment