有什么方法可以让Newtonsoft.Create在接口上调用您的自定义创建方法吗?

时间:2018-08-28 06:27:11

标签: c# interface json.net deserialization hangfire

我正在使用Hangfire运行自定义interface的多个任务,我们称之为IType。但是,由于Hangfire序列化了该方法,从而破坏了该类型的实例,因此当它尝试调用它时,我会收到如下错误消息:

  

Newtonsoft.Json.JsonSerializationException:无法创建IType类型的实例。类型是接口或抽象类,无法实例化。路径“东西”,第1行,位置17。      在Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject(...

我认为解决此问题的一种方法是针对每个class实例的interface可以存储其fully qualified domain name,然后可以使用reflection来返回它它需要的类型,唯一的问题是我不知道如何获取Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject()来调用我的反序列化方法。为了使这项工作有效,我需要一些attribute或某些特定的方法名称吗?

3 个答案:

答案 0 :(得分:2)

您需要指定一个JsonSerializerSettings,其中包含适当的TypeNameHandling值。这会将完全限定的名称嵌入JSON中的$type属性中,然后可以使用它来反序列化。这是一个完整的示例:

using System;
using Newtonsoft.Json;

interface IFoo
{
    void Method();
}

class Foo1 : IFoo
{
    public string Name { get; set; }
    public void Method() => Console.WriteLine("Method in Foo1");
}

class Foo2 : IFoo
{
    public int Value { get; set; }
    public void Method() => Console.WriteLine("Method in Foo2");
}

class Root
{
    public IFoo First { get; set; }
    public IFoo Second { get; set; }
}

class Test
{
    static void Main()
    {
        Root root = new Root
        { 
            First = new Foo1 { Name = "Fred" },
            Second = new Foo2 { Value = 10 }
        };
        var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };
        string json = JsonConvert.SerializeObject(root, settings);

        Console.WriteLine(json);

        Root root2 = JsonConvert.DeserializeObject<Root>(json, settings);
        root2.First.Method();
        root2.Second.Method();
    }
}

输出,显示JSON和Root中的接口属性已适当反序列化的事实:

{"$type":"Root, Test","First":{"$type":"Foo1, Test","Name":"Fred"},"Second":{"$type":"Foo2, Test","Value":10}}
Method in Foo1
Method in Foo2

您可能要使用其他TypeNameHandling个值代替All-有关详细信息,请参见the documentation

答案 1 :(得分:1)

为了完整起见,在您的Hangfire中将@Daisy的答案应用于StartUp(这是.NET Core的意思):

app.UseHangfireDashboard("/hangfire", ...);

app.UseHangfireServer(...);

JobHelper.SetSerializerSettings(new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.All
});

答案 2 :(得分:0)

.Net核心

GlobalConfiguration.Configuration.UseSerializerSettings(new JsonSerializerSettings
            {
                TypeNameHandling = TypeNameHandling.All
            })