Вы можете использовать Настраиваемый ISerializationBinder , чтобы указать настраиваемое значение $ type во время сериализации, а также для обработки того же настраиваемого значения $ type во время десериализации.
То есть вместо из:
"$type":"CharacterData, WorldServer"
Мы можем сериализовать в:
"$type":"CharacterData, Global"
И можем преобразовать это на приемном конце в известный CharacterData
тип.
-
Обратите внимание, что при использовании TypeNameHandling = TypeNameHandling.Auto
наше связующее будет вызываться только в том случае, если тип сериализуемого объекта не совпадает с его объявленным типом. Я думаю, что это уже для вас, поэтому не должно быть никаких проблем в этом отношении.
Пожалуйста, позвольте мне напомнить вам, что эта реализация должна быть закодирована с обеих сторон.
Чтобы убедиться в соответствии концепции вашему случаю; Я импровизировал следующую иерархию, где Transmission - это передаваемый объект.
public class Transmission
{
public TransmissionData Data { get; set; }
}
public class TransmissionData
{
}
public class CharacterData : TransmissionData
{
public string CharacterId { get; set; }
}
Вот пример преобразователя:
public class CharacterDataSerializationBinder : ISerializationBinder
{
DefaultSerializationBinder defaultBinder = new DefaultSerializationBinder();
void ISerializationBinder.BindToName(Type serializedType, out string assemblyName, out string typeName)
{
if (serializedType == typeof(CharacterData))
{
assemblyName = "Global";
typeName = serializedType.Name;
}
else
{
defaultBinder.BindToName(serializedType, out assemblyName, out typeName);
}
}
Type ISerializationBinder.BindToType(string assemblyName, string typeName)
{
if (typeName == typeof(CharacterData).Name && assemblyName == "Global")
{
return typeof(CharacterData);
}
else
{
return defaultBinder.BindToType(assemblyName, typeName);
}
}
}
И вот как его использовать:
Transmission SendData = new Transmission()
{
Data = new CharacterData() { CharacterId = "454" }
};
string JSonData = JsonConvert.SerializeObject(SendData, Formatting.None, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
SerializationBinder = new CharacterDataSerializationBinder()
});
Transmission deserializedJson = JsonConvert.DeserializeObject<Transmission>(JSonData, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
SerializationBinder = new CharacterDataSerializationBinder()
});
А вот вывод сериализации:
{"Data":{"$type":"CharacterData, Global","CharacterId":"454"}}
Надеюсь, это поможет.
ОБНОВЛЕНИЕ 1: ОП спросил, могут ли они использовать System.Runtime.Serialization.SerializationBinder
вместо Json. Net s ISerializationBinder
Ответ - да. Json. Net поддерживает этот тип связующего вместе со своим собственным.
Вот пример реализации этого вида связующего:
public class CharacterDataCoreBinder : SerializationBinder
{
public override void BindToName(Type serializedType, out string assemblyName, out string typeName)
{
typeName = serializedType.FullName;
if (serializedType == typeof(CharacterData))
{
assemblyName = "Global";
}
else
{
assemblyName = serializedType.Assembly.GetName().Name;
}
}
public override Type BindToType(string assemblyName, string typeName)
{
if (typeName == typeof(CharacterData).FullName && assemblyName == "Global")
{
return typeof(CharacterData);
}
else
{
return Type.GetType(typeName + ", " + assemblyName);
}
}
}
А вот как использовать это при сериализации / десериализации с Json. Net:
string JSonData = JsonConvert.SerializeObject(SendData, Formatting.None, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
// SerializationBinder = new CharacterDataSerializationBinder()
Binder = new CharacterDataCoreBinder()
});
Transmission deserializedJson = JsonConvert.DeserializeObject<Transmission>(JSonData, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto,
// SerializationBinder = new CharacterDataSerializationBinder()
Binder = new CharacterDataCoreBinder()
});