使用F#,我有一些配置要使用Newtonsoft.Json序列化到磁盘。配置数据是记录类型。记录类型中的一个字段是string-> bool类型的函数,用于将字符串与给定值进行比较。例如
<script src="/socket.io/socket.io.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script>
var socket = io.connect('http://localhost:4200');
function sendMsg(){
alert("OK");
socket.emit('sendmsg', document.getElementById("text").value);
}
</script>
<h2>Awesome Chat by Simon</h2>
<br>
<input type="text" id="text">
<input type="button" onclick="sendMsg()" value="Senden">
成功序列化类型,但是未成功存储字段(将其记录为“ {}”),因此反序列化失败。这似乎是设计使然。
如何存储一个函数,以便在反序列化后仍可将其用于从磁盘填充记录类型?
我已经将引号视为将表达式存储为数据的一种方式,但是我不确定这是否可行。如果是这样的话,我就在努力工作。
如何实现我所需要的?
更新;
(fun (x:string) -> x = "1")
记录类型存储配置;
type Logic = string -> bool
排除记录由用户填充,并针对某些数据集运行,这些数据集排除了返回集合中的项目。 QItem表示应用了Logic函数的数据集中的字符串,如果返回true,则ExcludedItems中的项目将从结果中排除。
最初,配置是由用户在解决方案中创建的,因此一切正常。但是,一旦创建了配置,我希望能够将配置保存到光盘上,以便可以将其加载并在需要时再次运行。
所以我需要能够存储它,但是我希望能够将其存储为字符串,然后在加载时再次运行它。
答案 0 :(得分:3)
您可以将函数序列化为JSON,然后反序列化并稍后使用FSPickler执行该函数:
open MBrace.FsPickler
open MBrace.FsPickler.Json
open System.IO
open System.Text
let serializer = JsonSerializer(indent = true)
let utf8 = UTF8Encoding(false)
let toJson (x: 'a) =
use stream = new MemoryStream()
serializer.Serialize(stream, x)
stream.ToArray() |> utf8.GetString
let parseJson<'a> json =
use reader = new StringReader(json)
serializer.Deserialize<'a>(reader)
let f = fun x -> x + 1
let serialized = toJson f
let deserialized = parseJson<int -> int> serialized
deserialized 1 // returns 2
该函数的序列化JSON如下所示:
{
"FsPickler": "4.0.0",
"type": "Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,System.Int32]",
"value": {
"_flags": "subtype",
"subtype": {
"Case": "NamedType",
"Name": "FSI_0002+serialized@23",
"Assembly": {
"Name": "FSI-ASSEMBLY",
"Version": "0.0.0.0",
"Culture": "neutral",
"PublicKeyToken": ""
}
},
"instance": {}
}
}
尽管instance
为空,但它记录有关为该函数创建的匿名类型的元数据。这样,只要调用反序列化的AppDomain中的函数类型可用,它就可以在调用反序列化版本时调用正确的代码。
编辑
如果您想对函数的逻辑进行字面序列化,则可以使用FSPickler来对代码引号进行序列化:
open MBrace.FsPickler
open MBrace.FsPickler.Json
open FSharp.Quotations
open FSharp.Quotations.Evaluator
open System.IO
open System.Text
let serializer = JsonSerializer(indent = true)
let utf8 = UTF8Encoding(false)
let toJson (x: 'a) =
use stream = new MemoryStream()
serializer.Serialize(stream, x)
stream.ToArray() |> utf8.GetString
let parseJson<'a> json =
use reader = new StringReader(json)
serializer.Deserialize<'a>(reader)
let f = <@ fun x -> x + 1 @>
let serialized = toJson f
let deserialized = parseJson<Expr<int -> int>> serialized
let increment = deserialized |> QuotationEvaluator.Evaluate
increment 1
通过这种方式,引号被序列化为JSON,并将所有逻辑描述为一个表达式树,当您对它进行反序列化时,可以使用FSharp.Quotations.Evaluator库将其转换为可调用的可运行函数。 / p>
JSON现在更大了,但是可以在任何地方反序列化和评估它:
{
"FsPickler": "4.0.0",
"type": "Microsoft.FSharp.Quotations.FSharpExpr`1[Microsoft.FSharp.Core.FSharpFunc`2[System.Int32,System.Int32]]",
"value": {
"attribs": [
{
"attribs": [],
"term": {
"Case": "CombTerm",
"Item1": {
"Case": "NewTupleOp",
"Item": {
"Case": "GenericTypeInstance",
"GenericDefinition": {
"Case": "NamedType",
"Name": "System.Tuple`2",
"Assembly": {
"Name": "mscorlib",
"Version": "4.0.0.0",
"Culture": "neutral",
"PublicKeyToken": "b77a5c561934e089"
}
},
"TypeArgs": [
{
"Case": "NamedType",
"Name": "System.String",
"Assembly": {
"_flags": "cached",
"id": 9
}
},
{
"Case": "GenericTypeInstance",
"GenericDefinition": {
"Case": "NamedType",
"Name": "System.Tuple`5",
"Assembly": {
"_flags": "cached",
"id": 9
}
},
"TypeArgs": [
{
"_flags": "cached",
"id": 11
},
{
"Case": "NamedType",
"Name": "System.Int32",
"Assembly": {
"_flags": "cached",
"id": 9
}
},
{
"_flags": "cached",
"id": 15
},
{
"_flags": "cached",
"id": 15
},
{
"_flags": "cached",
"id": 15
}
]
}
]
}
},
"Item2": [
{
"attribs": {
"_flags": "cached",
"id": 4
},
"term": {
"Case": "CombTerm",
"Item1": {
"Case": "ValueOp",
"Item1": {
"_flags": "subtype",
"subtype": {
"_flags": "cached",
"id": 11
},
"instance": "DebugRange"
},
"Item2": {
"_flags": "cached",
"id": 11
},
"Item3": null
},
"Item2": {
"_flags": "cached",
"id": 4
}
}
},
{
"attribs": {
"_flags": "cached",
"id": 4
},
"term": {
"Case": "CombTerm",
"Item1": {
"Case": "NewTupleOp",
"Item": {
"_flags": "cached",
"id": 12
}
},
"Item2": [
{
"attribs": {
"_flags": "cached",
"id": 4
},
"term": {
"Case": "CombTerm",
"Item1": {
"Case": "ValueOp",
"Item1": {
"_flags": "subtype",
"subtype": {
"_flags": "cached",
"id": 11
},
"instance": "C:\\Users\\aeshbach\\AppData\\Local\\Temp\\~vs220A.fsx"
},
"Item2": {
"_flags": "cached",
"id": 11
},
"Item3": null
},
"Item2": {
"_flags": "cached",
"id": 4
}
}
},
{
"attribs": {
"_flags": "cached",
"id": 4
},
"term": {
"Case": "CombTerm",
"Item1": {
"Case": "ValueOp",
"Item1": {
"_flags": "subtype",
"subtype": {
"_flags": "cached",
"id": 15
},
"instance": 32
},
"Item2": {
"_flags": "cached",
"id": 15
},
"Item3": null
},
"Item2": {
"_flags": "cached",
"id": 4
}
}
},
{
"attribs": {
"_flags": "cached",
"id": 4
},
"term": {
"Case": "CombTerm",
"Item1": {
"Case": "ValueOp",
"Item1": {
"_flags": "subtype",
"subtype": {
"_flags": "cached",
"id": 15
},
"instance": 11
},
"Item2": {
"_flags": "cached",
"id": 15
},
"Item3": null
},
"Item2": {
"_flags": "cached",
"id": 4
}
}
},
{
"attribs": {
"_flags": "cached",
"id": 4
},
"term": {
"Case": "CombTerm",
"Item1": {
"Case": "ValueOp",
"Item1": {
"_flags": "subtype",
"subtype": {
"_flags": "cached",
"id": 15
},
"instance": 32
},
"Item2": {
"_flags": "cached",
"id": 15
},
"Item3": null
},
"Item2": {
"_flags": "cached",
"id": 4
}
}
},
{
"attribs": {
"_flags": "cached",
"id": 4
},
"term": {
"Case": "CombTerm",
"Item1": {
"Case": "ValueOp",
"Item1": {
"_flags": "subtype",
"subtype": {
"_flags": "cached",
"id": 15
},
"instance": 25
},
"Item2": {
"_flags": "cached",
"id": 15
},
"Item3": null
},
"Item2": {
"_flags": "cached",
"id": 4
}
}
}
]
}
}
]
}
}
],
"term": {
"Case": "LambdaTerm",
"Item1": {
"isMutable104": false,
"name": "x",
"stamp": 0,
"typ": {
"_flags": "cached",
"id": 15
}
},
"Item2": {
"attribs": {
"_flags": "cached",
"id": 4
},
"term": {
"Case": "CombTerm",
"Item1": {
"Case": "StaticMethodCallOp",
"Item": {
"Case": "GenericMethodInstance",
"GenericDefinition": {
"Case": "Method",
"Signature": "T3 op_Addition[T1,T2,T3](T1,T2)",
"IsStatic": true,
"DeclaringType": {
"Case": "NamedType",
"Name": "Microsoft.FSharp.Core.Operators",
"Assembly": {
"Name": "FSharp.Core",
"Version": "4.4.1.0",
"Culture": "neutral",
"PublicKeyToken": "b03f5f7f11d50a3a"
}
},
"ReflectedType": null
},
"TypeArgs": [
{
"_flags": "cached",
"id": 15
},
{
"_flags": "cached",
"id": 15
},
{
"_flags": "cached",
"id": 15
}
]
}
},
"Item2": [
{
"attribs": {
"_flags": "cached",
"id": 4
},
"term": {
"Case": "VarTerm",
"Item": {
"_flags": "cached",
"id": 40
}
}
},
{
"attribs": {
"_flags": "cached",
"id": 4
},
"term": {
"Case": "CombTerm",
"Item1": {
"Case": "ValueOp",
"Item1": {
"_flags": "subtype",
"subtype": {
"_flags": "cached",
"id": 15
},
"instance": 1
},
"Item2": {
"_flags": "cached",
"id": 15
},
"Item3": null
},
"Item2": {
"_flags": "cached",
"id": 4
}
}
}
]
}
}
}
}
}