How should I expose a global Dictionary declared in f# that will have items added from different HttpModules?
I have a dictionary (formatters) declared in the following code that will have items added to it inside of multiple HttpModules. Once those are loaded it will not be written to again. What would be the best way to expose this so it can be accessed from any .NET language? I know this seems lame and looks like I should just have them implement ToString() however part of the application requires strings to be in a certain format and I don't want clients having to implement ToString() in a way that is specific to my application.
module MappingFormatters
open System
open System.Collections.Generic
let formatters = new Dictionary<Type, obj -> string>();
let format item =
let toDateTime (d:DateTime) =
let mutable date = d;
if (date.Kind) <> System.DateTimeKind.Utc then
date <- date.ToUniversalTime()
date.ToString("yyyy-MM-ddTHH:mm:00Z")
let stripControlCharacters (str:string) =
let isControl c = not (Char.IsControl(c))
System.String( isControl |> Array.filter <| str.ToCharArray())
let defaultFormat (item:obj) =
match item with
| :? string as str-> stripControlCharacters(str)
| :? DateTime as dte -> toDateTime(dte)
| _ -> item.开发者_如何学PythonToString()
let key = item.GetType();
if formatters.ContainsKey(key) then
formatters.Item(key) item
else
defaultFormat item
If the question is just one about language interoperability, then I think you should just change the type from
Dictionary<Type, obj -> string>
to
Dictionary<Type, Func<obj, string> >
and then you should be in good shape.
After researching. I have decided to create a type called MappingFormatters to hold the method for adding the formatter. The client does not need to call it, but my f# code will. I believe this will let me use the common f# conventions while exposing a way for other .net languages to inter-operate with the least confusion.
module File1
open System
let mutable formatters = Map.empty<string, obj -> string>
let format (item:obj) =
let dateToString (d:DateTime) =
let mutable date = d;
if (date.Kind) <> System.DateTimeKind.Utc then
date <- date.ToUniversalTime()
date.ToString("yyyy-MM-ddTHH:mm:00Z")
let stripCtrlChars (str:string) =
let isControl c = not (Char.IsControl(c))
System.String( isControl |> Array.filter <| str.ToCharArray())
let key = item.GetType().AssemblyQualifiedName
if Map.containsKey key formatters then
Map.find key formatters item
else
match item with
| :? DateTime as d -> dateToString d
| _ -> stripCtrlChars (item.ToString())
let add (typ:Type) (formatter:obj -> string) =
let contains = Map.containsKey
let key = typ.AssemblyQualifiedName
if not (formatters |> contains key) then
formatters <- Map.add key formatter formatters
type MappingFormatters() = class
let addLock = new obj()
member a.Add (``type``:Type, formatter:Func<obj,string>) =
lock addLock (fun () ->
add ``type`` (fun x -> formatter.Invoke(x))
)
end
精彩评论