Serializar a XML e incluir el tipo de objeto serializado
-
05-07-2019 - |
Pregunta
En una pregunta anterior sobre serializar un objeto en un XmlDocument
en C # , necesitaba serializar cierta información de falla en un XmlDocument
que fue devuelto por una llamada de servicio web de estilo asmx. En el cliente necesito eliminar la serialización del XmlDocument
de nuevo a un objeto.
Esto es bastante sencillo si conoce el tipo, pero me di cuenta de que quería un enfoque flexible en el que el tipo de deserialización también esté codificado en el XmlDocument
. Actualmente lo estoy haciendo manualmente agregando un XmlNode
al XmlDocument
que tiene el nombre del tipo, calculado de la siguiente manera:
Type type = fault.GetType();
string assemblyName = type.Assembly.FullName;
// Strip off the version and culture info
assemblyName = assemblyName.Substring(0, assemblyName.IndexOf(",")).Trim();
string typeName = type.FullName + ", " + assemblyName;
Luego, en el cliente, primero obtengo este nombre de tipo del XmlDocument
, y creo el objeto de tipo que se pasa al XmlSerialiser
de esta manera:
object fault;
XmlNode faultNode = e.Detail.FirstChild;
XmlNode faultTypeNode = faultNode.NextSibling;
// The typename of the fault type is the inner xml of the first node
string typeName = faultTypeNode.InnerXml;
Type faultType = Type.GetType(typeName);
// The serialised data for the fault is the second node
using (var stream = new StringReader(faultNode.OuterXml))
{
var serialiser = new XmlSerializer(faultType);
objectThatWasSerialised = serialiser.Deserialize(stream);
}
return (CastToType)fault;
Entonces, este es un enfoque de fuerza bruta, y me preguntaba si hay una solución más elegante que de alguna manera incluya el nombre de tipo del tipo serializado automáticamente, en lugar de grabarlo manualmente en otro lugar.
Solución
Me enfrenté a un problema similar y se me ocurrió la misma solución. En lo que a mí respecta, esa es la única forma de mantener los tipos junto con los valores en la serialización XML.
Veo que estás cortando la versión de ensamblaje como yo también. Pero me gustaría mencionar que tendrá problemas con los tipos genéricos, ya que su firma se ve así:
System.Nullable`1[[System.Int, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Así que hice una función para cortar solo las versiones de ensamblaje, lo que parece ser suficiente para deshacerse de los problemas de versiones:
private static string CutOutVersionNumbers(string fullTypeName)
{
string shortTypeName = fullTypeName;
var versionIndex = shortTypeName.IndexOf("Version");
while (versionIndex != -1)
{
int commaIndex = shortTypeName.IndexOf(",", versionIndex);
shortTypeName = shortTypeName.Remove(versionIndex, commaIndex - versionIndex + 1);
versionIndex = shortTypeName.IndexOf("Version");
}
return shortTypeName;
}
Otros consejos
Neil, ¿por qué necesitas que sea del tipo mismo tanto en el cliente como en el servidor?
¿Sigue utilizando ASMX en el cliente? Esa sería una razón, ya que ASMX no admite fallas correctamente.
Además, ¿tiene tantos tipos de fallas diferentes que una simple instrucción switch no puede determinar el tipo correcto de usar?