Есть ли способ, чтобы Newtonsoft.Create вызывал ваш пользовательский метод создания на интерфейсе? - PullRequest
0 голосов
/ 28 августа 2018

Я использую 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 или какое-то конкретное имя метода, которое мне нужно иметь, чтобы эта работа работала?

Ответы [ 2 ]

0 голосов
/ 28 августа 2018

Для полноты, применить ответ @ Daisy к Hangfire, в вашем StartUp (это для .NET Core):

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

app.UseHangfireServer(...);

JobHelper.SetSerializerSettings(new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.All
});
0 голосов
/ 28 августа 2018

Вам необходимо указать 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 - подробности см. В документации .

...