在RavenDB中使用Func <t,tresult =“”>成员存储类</t,>

时间:2014-04-20 21:47:02

标签: c# serialization json.net ravendb

我有一个班级

class Test 
{
    public string SomeValue { get; set; }
    public Func<int, string> DoStuff { get; set; }
}

然后我将其实例化为以下

Test t = new Test();
t.SomeValue = "Your number: ";
t.DoStuff = (n) => { return t.SomeValue + n.ToString(); }; 

在此之后,我尝试将t存储在RavenDB中

RavenSession.Store(t);
RavenSession.SaveChanges(); // This fails

正如上面的评论所述,RavenSession.SaveChanges()失败并显示消息

  

Raven.Imports.Newtonsoft.Json.JsonSerializationException:Self   为属性&#39;扩展&#39;检测到的引用循环与类型   &#39; ExampleProject.Test。路径&#39; DoStuff.target0&#39;。

但是,当我像这样使用Json.NET序列化对象时

string s = Newtonsoft.Json.JsonConvert.SerializeObject(t);

对象被序列化得很好,没有错误。

我是否必须以不同方式配置RavenDB会话? (我使用所有默认值)

我已经尝试将[JsonObject(IsReference = true)]添加到课程Test,这对我们没有帮助。

1 个答案:

答案 0 :(得分:4)

代理不能被序列化,因为它们不包含数据而是代码(代表类型包含一些数据,但这里没有任何用处)。您要做的事情将被视为编组。

反序列化后,您的闭包将不再有效:

Test t = new Test();
t.SomeValue = "Your number: ";
t.DoStuff = (n) => { return t.SomeValue + n.ToString(); };

var deserialized = JsonConvert.Deserialize<Test>(JsonConvert.Serialize(t));
var yourNumber = deserialized.DoStuff(1); // What the heck happens here??

但是,我甚至无法让Func对Json.Net进行序列化,因为它没有正确实现ISerializable:

class FuncTest
{
    public Func<int, string> DoStuff { get; set; }
    public string Value { get; set; }
}

[Test]
public void Test_Func()
{
    var test = new FuncTest();
    test.DoStuff = (num) => num.ToString();

    var deserialized = JsonConvert.DeserializeObject<FuncTest>(JsonConvert.SerializeObject(test));
    deserialized.Value = deserialized.DoStuff(5);

    Assert.That(deserialized.Value == "5");
}

Newtonsoft.Json.JsonSerializationException:ISerializable type&#39; System.Func`2 [System.Int32,System.String]&#39;没有有效的构造函数。要正确实现ISerializable,应该存在一个采用SerializationInfo和StreamingContext参数的构造函数。

无论如何,在反序列化之后,您不应期望代理的价值保留。我会在委托上使用[JsonIgnore]属性来确保跨Json.Net配置的一致行为。