C# .net 5 knowntype не работает при сериализации классов из других библиотек

введите сюда описание изображенияЕсть базовый класс в основном ядре *.dll:

[KnownType("GetRealizations")]
[DataContract]
public abstract class AnimalBase
{
    [DataMember]
    public string Name { get; set; }
    public AnimalBase()
    {
    }
    public static List<Type> GetRealizations() => typeof(AnimalBase).GetRealizations();
}

Есть класс-наследник, реализованный в другом ядре *.dll:

[DataContract]
public class AnimalDog : AnimalBase
{
    [DataMember]
    public string Description { get; set; }
    [DataMember]
    public string HomeAdress { get; set; }

    public AnimalDog()
    {
    }
}

Поиск типов (GetRealizations) организован следующим способом:

public static class AssemblyHelper
{
    public static List<Type> GetRealizations(this Type type)
    {
        List<Type> res = new List<Type>();
        Action<Assembly> getRealizationsFrom = e =>
        {
            IEnumerable<Type> assignable = e.GetTypesSafe().Where(t => !t.IsAbstract && type.IsAssignableFrom(t));
            res.AddRange(assignable.ToList());
        };

        var files = new DirectoryInfo(Environment.CurrentDirectory).GetFiles("*.dll", SearchOption.TopDirectoryOnly).Select(x=>x.FullName).ToList();
        foreach (var f in files)
            try
            {
                getRealizationsFrom(Assembly.LoadFile(f));
            }
            catch (Exception)
            {
                continue;
            }

        return res;
    }

    private static Dictionary<string, Type[]> assebliesTypes = new Dictionary<string, Type[]>();
    public static Type[] GetTypesSafe(this Assembly assembly)
    {
        if (assebliesTypes.ContainsKey(assembly.FullName))
            return assebliesTypes[assembly.FullName];

        Type[] tt = null;
        try
        {
            tt = assembly.GetTypes();
        }
        catch (ReflectionTypeLoadException ex)
        {
            tt = ex.Types.Where(t => t != null).ToArray();
        }
        assebliesTypes.Add(assembly.FullName, tt);
        return tt;
    }
}

Сериализатор реализован следующим образом:

public static class Serializer
{
    public static void Serialize<T>(this T obj, string path)
    {
        DataContractJsonSerializer js = new DataContractJsonSerializer(typeof(T));
        try
        {
            using (FileStream fs = new FileStream(path, FileMode.Create))
                js.WriteObject(fs, obj);
        }
        catch (Exception ex)
        {
            throw new Exception($"Ошибка при сериализации в файл {path} : {ex.Message}");
        }
    }
}

Пример использования в консольном приложении:

        List<AnimalBase> animals = new List<AnimalBase>() 
        { 
            new AnimalDog() { Name = "Собачка1", Description = "Коричневая", HomeAdress = "Пушкина 2" },
            new AnimalDog() { Name = "Собачка2", Description = "Белая", HomeAdress = "Маркса 4" }
        };
        Serializer.Serialize(animals, "D:\\11111.json");

В сериализаторе получаю ошибку: Type 'TinkSampleNet.AnimalDog' with data contract name 'AnimalDog:http://schemas.datacontract.org/2004/07/TinkSampleNet' is not expected. Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.

В отладке вижу, что GetRealizations возвращает необходимые типы сериализватору.

ПРИ ЭТОМ в приложении .Net Framework все работает. Также работает, если в KnownType базового абстрактного класса указать конкретные типы, но это невозможно, т.к. они находятся в других библиотеках.

Помогите, всю голову поломал себе уже...


Ответы (1 шт):

Автор решения: Алексей

Накидал вот такой класс, вроде работает, попозже проверю получше

public static class Serializer2
{
    private static readonly JsonSerializerSettings settings = new JsonSerializerSettings()
    {
        TypeNameHandling = TypeNameHandling.All,
        Formatting = Formatting.Indented
    };

    public static void Serialize(object obj, string fName)
    {
        if (obj == null)
        {
            throw new NullReferenceException();
        }

        string jsonString = Newtonsoft.Json.JsonConvert.SerializeObject(obj, settings);
        File.WriteAllText(fName, jsonString);
    }

    public static T Deserialize<T>(string fName)
    {
        string jsonString = File.ReadAllText(fName);
        T obj = JsonConvert.DeserializeObject<T>(jsonString, settings);
        return obj;
    }
}
→ Ссылка