简体   繁体   中英

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.ToString()

    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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM