C# Newtonsoft.json序列化和反序列化来自共享项目的类的基/内写

C# Newtonsoft.json序列化和反序列化来自共享项目的类的基/内写,c#,json,serialization,json.net,shared-project,C#,Json,Serialization,Json.net,Shared Project,因此,我有两门课,如下所示。它们都位于同一名称空间和同一共享项目中 public class Person{ public string Name{get;set;} } public class EmployedPerson : Person{ public string JobTitle{get;set;} } 当我将这些项序列化为rabbitmq时,我将序列化为基类,如下所示: JsonSerializerSettings settings = new JsonSerial

因此,我有两门课,如下所示。它们都位于同一名称空间和同一共享项目中

public class Person{
   public string Name{get;set;}
}

public class EmployedPerson : Person{
   public string JobTitle{get;set;}
}
当我将这些项序列化为rabbitmq时,我将序列化为基类,如下所示:

JsonSerializerSettings settings = new JsonSerializerSettings
{
   TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
   TypeNameHandling = TypeNameHandling.Objects
};
JsonConvert.SerializeObject(input, settings)
然而,当反序列化时,我遇到了问题。我希望能够执行如下所示的操作,将其反序列化为基类,然后检查它是否为inheirited类型

类型检查:

Person person = Deserialize<Person>(e.Body, Encoding.Unicode);
   if (person is EmployedPerson)
   {
    logger.LogInformation("This person has a job!");
    }
反序列化逻辑:

    private static T Deserialize<T>(byte[] data, Encoding encoding) where T : class
    {
        try
        {
            using (MemoryStream stream = new MemoryStream(data))
            using (StreamReader reader = new StreamReader(stream, encoding))
                return JsonSerializer.Create(settings).Deserialize(reader, typeof(T)) as T;
        }
        catch (Exception e)
        {
            Type typeParameter = typeof(T);
            logger.LogError(LogEvent.SERIALIZATION_ERROR, e, "Deserializing type {@TypeName} failed", typeParameter.Name);
            logger.LogInformation(Encoding.UTF8.GetString(data));
            return default(T);
        }
    }

谢谢@dbc,据我所知,您建议编写自定义SerializationBinder是解决我问题的最佳方法

我使用的KnownTypesBinder在以下位置实施:

知识绑定器:

public class KnownTypesBinder : ISerializationBinder
    {
        public IList<Type> KnownTypes { get; set; }

        public Type BindToType(string assemblyName, string typeName)
        {
            return KnownTypes.SingleOrDefault(t => t.Name == typeName);
        }

        public void BindToName(Type serializedType, out string assemblyName, out string typeName)
        {
            assemblyName = null;
            typeName = serializedType.Name;
        }
    }
创建设置对象后,我将其传递到JsonConvert序列化函数中

JsonConvert.DeserializeObject<T>(Encoding.Unicode.GetString(input), settings) 
JsonConvert.DeserializeObject(Encoding.Unicode.GetString(输入),设置)
还请注意,KnownTypesBinder中的KnownTypes必须预先填充所有要反序列化的非基本类型

编辑: 我目前不接受自己的答案,因为我不知道如何处理复杂类型的列表。例如,如果一个人有一个列表和一个列表,那么当typeName为“List`1”并且可以是其中之一时,您将返回什么类型

编辑 以下版本的KnownTypesBinder解决了我与对象列表相关的问题

public class KnownTypesBinder: ISerializationBinder
{
    public IList<Type> KnownTypes { get; set; }

    public Type BindToType(string assemblyName, string typeName)
    {
        return KnownTypes.SingleOrDefault(t => t.UnderlyingSystemType.ToString() == typeName);
    }

    public void BindToName(Type serializedType, out string assemblyName, out string typeName)
    {
        assemblyName = null;
        typeName = serializedType.UnderlyingSystemType.ToString();
    }
}
公共类KnownTypesBinder:ISerializationBinder
{
公共IList KnownTypes{get;set;}
公共类型BindToType(字符串程序集名称、字符串类型名称)
{
返回KnownTypes.SingleOrDefault(t=>t.UnderlyingSystemType.ToString()==typeName);
}
public void BindToName(类型serializedType、输出字符串assemblyName、输出字符串typeName)
{
assemblyName=null;
typeName=serializedType.UnderlineingSystemType.ToString();
}
}

我想这可能是你问题的答案:你可以写一篇文章。如前所述,出于安全考虑,编写自己的绑定来清理反序列化类型也是一个好主意。2) 发出您自己的自定义类型属性,并使用自定义的
JsonConverter
解析它,如图所示,例如,在查看SerializationBinder时。我感到困惑。如果类型在共享项目中,为什么队列两端的程序集名称不同?因为共享项目不创建自己的程序集。他们被吸收到使用它的项目中。
settings = new JsonSerializerSettings
{
    TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
    TypeNameHandling = TypeNameHandling.Objects,
    SerializationBinder = new KnownTypesBinder()
};
JsonConvert.DeserializeObject<T>(Encoding.Unicode.GetString(input), settings) 
public class KnownTypesBinder: ISerializationBinder
{
    public IList<Type> KnownTypes { get; set; }

    public Type BindToType(string assemblyName, string typeName)
    {
        return KnownTypes.SingleOrDefault(t => t.UnderlyingSystemType.ToString() == typeName);
    }

    public void BindToName(Type serializedType, out string assemblyName, out string typeName)
    {
        assemblyName = null;
        typeName = serializedType.UnderlyingSystemType.ToString();
    }
}