csbiology / dynamicobj Goto Github PK
View Code? Open in Web Editor NEWF# library supporting Dynamic Objects including inheritance in functional style
Home Page: https://csbiology.github.io/DynamicObj/
License: MIT License
F# library supporting Dynamic Objects including inheritance in functional style
Home Page: https://csbiology.github.io/DynamicObj/
License: MIT License
What API should be there?
I have a nested dynamic object type:
let response =
[
"StatusCode", string result.Value.Response.StatusCode
"Time", (System.DateTime.Now.ToUniversalTime() - st).ToString()
]
|> List.map (fun x -> fst x, snd x |> Some)
let request =
let query =
let queryLogger = Logger()
ctx.Request.Query |> Seq.iter (fun x -> queryLogger.setProp(x.Key, Some x.Value) )
queryLogger
let headers =
let queryLogger = Logger()
ctx.Request.Headers |> Seq.iter (fun x -> queryLogger.setProp(x.Key, x.Value |> String.concat "," |> Some ) )
queryLogger
let userAgent =
ctx.Request.Headers
|> Seq.tryFind (fun x -> x.Key ="User-Agent")
|> Option.map (fun x -> x.Value |> String.concat ",")
|> Option.defaultValue ""
let contentType =
ctx.Request.Headers
|> Seq.tryFind (fun x -> x.Key ="Content-Type")
|> Option.map (fun x -> x.Value |> String.concat ",")
|> Option.defaultValue ""
[
"Path", box ctx.Request.Path
"PathBase", box ctx.Request.PathBase
"Method", box ctx.Request.Method
"Host", box ctx.Request.Host.Host
"Port",
if ctx.Request.Host.Port.HasValue then string ctx.Request.Host.Port.Value else ""
|> box
"QueryString",
if ctx.Request.QueryString.HasValue then string ctx.Request.Host.Port.Value else ""
|> box
"Query", if ctx.Request.Query.Count > 0 then box query else null
"Headers", if ctx.Request.Headers.Count > 0 then box headers else null
"UserAgent", box userAgent
"ContentType", box contentType
]
|> List.map (fun x -> fst x, snd x |> Some)
let logger =
let props =
[
"Timestamp", st.ToString("yyyy.MM.dd hh:mm:ss.fffff") |> box
"Request", Logger.init(request) |> box
"Response", Logger.init(response) |> box
]
|> List.map (fun x -> fst x, snd x |> Some)
Logger.init(props)
The json export works:
logger |> JsonConvert.SerializeObject |> printfn "%A"
{
"Timestamp": "2022.03.25 12:53:37.89496",
"Request": {
"Path": "/api/IHelpdeskAPI/getCaptcha",
"PathBase": "",
"Method": "GET",
"Host": "localhost",
"Port": "8085",
"QueryString": "",
"Query": null,
"Headers": {
"Connection": "close",
"Content-Type": "application/json; charset=utf-8",
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8",
"Cookie": "ajs_anonymous_id=%22bf0866e7-3877-4d25-8805-c1b2a4b5bd71%22; isDarkmode=false",
"Host": "localhost:8085",
"Referer": "http://localhost:8080/?topic=Tools_Swate",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36 OPR/84.0.4316.42",
"sec-fetch-dest": "empty",
"sec-fetch-mode": "cors",
"sec-fetch-site": "same-origin",
"sec-ch-ua-platform": "\"Windows\"",
"sec-ch-ua-mobile": "?0",
"x-remoting-proxy": "true",
"sec-ch-ua": "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"98\", \"Opera\";v=\"84\""
},
"UserAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.109 Safari/537.36 OPR/84.0.4316.42",
"ContentType": "application/json; charset=utf-8"
},
"Response": {
"StatusCode": "200",
"Time": "00:00:24.8929431"
}
}
But DynObj.print logger
returns an error:
System.MemberAccessException: Cannot access member.
at DynamicObj.DynamicObj.op_Dynamic[b](b lookup, String name)
at DynamicObj.DynObj.loop@93-3(DynamicObj d, DynamicObj object, Int32 identationLevel, FSharpList`1 membersLeft, FSharpList`1 acc)
at DynamicObj.DynObj.loop@93-3(DynamicObj d, DynamicObj object, Int32 identationLevel, FSharpList`1 membersLeft, FSharpList`1 acc)
at System.Runtime.CompilerServices.RuntimeHelpers.DispatchTailCalls(IntPtr callersRetAddrSlot, IntPtr callTarget, IntPtr retVal)
at DynamicObj.DynObj.format(DynamicObj d)
at DynamicObj.DynObj.print(DynamicObj d)
So this is more or less a collection of things i found missing and i am not sure if these are even possible/how to implement them.
DynamicObj
. The workaround is to use CopyDynamicPropertiesTo
on the inerhiting type.type Logger() =
inherit DynamicObj()
let logger = Logger()
logger.SetValue ("key", "value")
let dynObj : DynamicObj = DynamicObj()
dynObj.SetValue ("key", "value")
// upcast
let d2 = logger :> DynamicObj // upcast works without issue
d2.TryGetValue "key" // Some "value"
// downcast
dynObj :?> Logger
// Error: System.InvalidCastException: Unable to cast object of type 'DynamicObj.DynamicObj' to type 'Logger'.
//workaround
dynObj.CopyDynamicPropertiesTo logger
TryGetTypedValue
member.type MyRecordType = {|
key: string
|}
let dynObj : DynamicObj = DynamicObj()
dynObj.SetValue ("key", "value")
dynObj :?> MyRecordType
// Type constraint mismatch. The type 'MyRecordType' is not compatible with type 'DynamicObj
https://stackoverflow.com/questions/17101329/f-sequence-comparison
We might want to do structural equality check in Equals
, as dynamic members having type seq<'A>
will fail on comparison even when they have the same items. This might be the last improvement to enable structural equality checks for charts in Plotly.NET.
Current impression is:
?
operator, implement the Item
accession method, and conditionally transpile as JSON field access (JS) or dictionary item access (python)There seems to be additional steps necessary to ensure that Newtonsoft.Json correctly serializes ImmutableDynamicObj
. See this comparison:
DynamicObj (works)
let works =
let foo = DynamicObj()
foo?bar <- [1;2;3;4]
foo
works |> JsonConvert.SerializeObject
val it : string = "{"bar":[1,2,3,4]}"
ImmutableDynamicObj (soes not work)
ImmutableDynamicObj()
|> ImmutableDynamicObj.add "foo" "bar"
|> JsonConvert.SerializeObject
val it : string = "{}"
Problems that arise from this are for example plotly/Plotly.NET#45
Ideally, both APIs should provide the exact same functionality. While the mutable operations on DO have no equivalents, here are some things we should do IMO:
DynObj
namespace (it is confusing), make all functions contained there static members of DynamicObj
Hello, i found AND fixed a bug in the DynObj.print function! I will open a PR soon.
To replicate the issue you can use a dynamic object, replicating the following json:
{
"serilog": {
"Level": "Information",
"MessageTemplate": "{Method} Request at {Path}"
}
}
OR
let o = DynamicObj()
let o2 = DynamicObj()
o2.SetValue("Level", "Information")
o2.SetValue("MessageTemplate","{Method} Request at {Path}")
o.SetValue("serilog", o2)
Using the current print function will lead to the following error:
System.MemberAccessException: Cannot access member.
at FSI_0009.loop@55-1(DynamicObj d, DynamicObj object, Int32 identationLevel, FSharpList`1 membersLeft, FSharpList`1 acc)
at FSI_0009.loop@55-1(DynamicObj d, DynamicObj object, Int32 identationLevel, FSharpList`1 membersLeft, FSharpList`1 acc)
at FSI_0009.format(DynamicObj d)
at FSI_0009.print(DynamicObj d)
at <StartupCode$FSI_0010>.$FSI_0010.main@()
Stopped due to error
This error is produced by line 105. In which the source dynamic object is given into the loop, instead of the current "parent"-dynamic object object
.
Will open a PR for this.
Hello!
In an effort to use Plotly.NET we'll likely need to strong-name sign this dependency as well.
See this issue for more details:
plotly/Plotly.NET#175
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.