我正在使用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
或某些特定的方法名称吗?
答案 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
})