Docs Menu
Docs Home
/ /

Serialización

En esta guía, puedes aprender a usar el driver de MongoDB .NET/C# para realizar la serialización. La serialización es el proceso de mapear un objeto de C# a un documento BSON para su almacenamiento en MongoDB.

Tip

Serialización

Para obtener más información sobre la serialización, consulte Artículo sobreserialización en Wikipedia.

Los serializadores son clases que gestionan la traducción de objetos de C# hacia y desde documentos BSON. Los serializadores implementan... IBsonSerializer interfaz. El controlador .NET/C# tiene muchos serializadores integrados diseñados para manejar tipos primitivos, tipos de colección y clases personalizadas.

Para ver una lista completa de serializadores disponibles, se puede consultar la Documentación de la API del namespace de serializadores.

La clase ObjectSerializer permite la serialización y deserialización solo de los tipos que se consideran seguros. Cuando se construye un ObjectSerializer, se puede pasar un delegado del tipo Func<Type, bool> Este delegado acepta un tipo de objeto Realm y devuelve un valor booleano que indica si el tipo es seguro para la serialización.

En la mayoría de los casos, pasa el delegado ObjectSerializer.DefaultAllowedTypes(). Este método devuelve true para varios tipos de frameworks conocidos que hemos considerado seguros. Para serializar tipos personalizados, se crea una expresión booleana que evalúa a true para los tipos que se quieren incluir. Luego, se añade esta expresión al final del delegado que se pasa al constructor ObjectSerializer.

En el siguiente ejemplo, ObjectSerializer serializará y deserializará cualquier tipo permitido por ObjectSerializer.DefaultAllowedTypes() o cuyo nombre completo empiece por "MyNamespace":

var objectSerializer = new ObjectSerializer(type => ObjectSerializer.DefaultAllowedTypes(type)
|| type.FullName.StartsWith("MyNamespace"));
BsonSerializer.RegisterSerializer(objectSerializer);

Para permitir la serialización de tipos anónimos, agrega la expresión booleana type.FullName.StartsWith("<>f__AnonymousType")) a tu delegado, como se muestra en el ejemplo siguiente:

var objectSerializer = new ObjectSerializer(type => ObjectSerializer.DefaultAllowedTypes(type)
|| type.FullName.StartsWith("<>f__AnonymousType"));
BsonSerializer.RegisterSerializer(objectSerializer);

Se puede crear y registrar el ObjectSerializer al comienzo del programa, antes de hacer cualquier otra cosa.

El registro del serializador contiene todos los serializadores registrados que están disponibles para la aplicación. Muchos de los serializadores incorporados se registran automáticamente en el registro del serializador durante el inicio de la aplicación.

Antes de poder utilizar un serializador personalizado, se debe añadir al registro de serializadores, como se muestra en el siguiente ejemplo:

BsonSerializer.RegisterSerializer(new CustomTypeSerializer());

Después de que se registre el serializador, el driver lo utiliza para serializar cualquier valor que esté mapeado por el serializador.

Para acceder a un serializador específico desde el registro, se debe utilizar la propiedad SerializerRegistry de la clase BsonSerializer de la siguiente manera:

var intSerializer = BsonSerializer.SerializerRegistry.GetSerializer<int>();

Importante

El registro del serializador es un registro global. Esto significa que no puedes utilizar varios registros en una sola aplicación.

Para crear un serializador personalizado, se debe implementar la clase base IBsonSerializer, configurar al miembro ValueType y sobrescribir los métodos Deserialize() y Serialize().

En el siguiente ejemplo de código, se muestra un serializador BsonRegularExpression personalizado:

class CustomRegularExpressionSerializer : IBsonSerializer
{
public Type ValueType => typeof(Regex);
public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
var type = context.Reader.CurrentBsonType;
switch (type)
{
case BsonType.RegularExpression:
return context.Reader.ReadRegularExpression().AsRegex;
case BsonType.String:
var pattern = context.Reader.ReadString()
return new Regex(pattern);
default:
throw new NotSupportedException($"Cannot convert a {type} to a RegularExpression.");
}
}
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
{
var regex = (Regex) value;
context.Writer.WriteRegularExpression(regex);
}
}

El driver .NET/C# tiene varias interfaces opcionales que tu clase de serializador personalizada puede implementar, según el tipo de datos que gestione el serializador.

La interfaz IBsonIdProvider proporciona los métodos GetDocumentId() y SetDocumentId(), y es útil si el objeto que se está serializando utiliza un tipo de _id distinto de ObjectId.

El siguiente ejemplo de código muestra un serializador personalizado que implementa la interfaz IBsonIdProvider:

class CustomPersonSerializer : IBsonSerializer, IBsonIdProvider
{
public Type ValueType => typeof(Person);
public bool GetDocumentId(object document, out object id, out Type idNominalType, out IIdGenerator idGenerator)
{
var person = (Person)document;
id = person.Id;
idNominalType = typeof(string);
idGenerator = new StringObjectIdGenerator();
return true;
}
public void SetDocumentId(object document, object id)
{
var person = (Person)document;
person.Id = (string)id;
}
public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
// Deserialization logic
}
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
{
// Serialization logic
}
}

Implementar la interfaz IBsonDocumentSerializer permite al driver acceder a la información de los nodos del objeto que se está serializando. Esto permite al driver construir correctamente queries con seguridad de tipos al utilizar un serializador personalizado.

El siguiente ejemplo de código muestra un serializador personalizado que implementa la interfaz IBsonDocumentSerializer:

class CustomPersonSerializer : IBsonSerializer, IBsonDocumentSerializer
{
public Type ValueType => typeof(Person);
public bool GetMemberSerializationInfo(string memberName, out BsonSerializationInfo serializationInfo)
{
switch (memberName)
{
case "Name":
serializationInfo = new BsonSerializationInfo("name", new StringSerializer(), typeof(string));
return true;
case "Age":
serializationInfo = new BsonSerializationInfo("age", new Int32Serializer(), typeof(int));
return true;
default:
serializationInfo = null;
return false;
}
}
public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
// Deserialization logic
}
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
{
// Serialization logic
}
}

Implementar la interfaz IBsonArraySerializer permite al driver acceder a la información de serialización de elementos individuales en un arreglo.

El siguiente ejemplo de código muestra un serializador personalizado que implementa la interfaz IBsonArraySerializer:

class CustomListSerializer : IBsonSerializer, IBsonArraySerializer
{
public Type ValueType => typeof(List<string>);
public bool TryGetItemSerializationInfo(out BsonSerializationInfo serializationInfo)
{
serializationInfo = new BsonSerializationInfo("item", new StringSerializer(), typeof(string));
return true;
}
public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
// Deserialization logic
}
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
{
// Serialization logic
}
}

Los paquetes de convenciones te permiten definir y aplicar convenciones a tus clases y sus nodos que el driver utiliza durante la serialización. Las convenciones especifican cómo se asignan los datos entre tus objetos de C# y los documentos de MongoDB sin necesidad de decorar cada clase con atributos.

El driver de .NET/C# proporciona convenciones incorporadas que puedes usar para personalizar el proceso de serialización. En la siguiente tabla, se describen algunas de las convenciones incorporadas:

Convención
Descripción

Convierte los nombres de los elementos a camel case durante la serialización y la deserialización.

Convierte los valores de enum a una representación especificada durante la serialización y la deserialización.

Especifica si se deben ignorar los elementos extra de un documento durante la deserialización.

Especifica qué tipos se pueden serializar mediante un serializador de objetos.

Para ver la lista completa de convenciones disponibles, se puede consultar la referencia de clase Convenciones en la Documentación de la API.

Para registrar una convención, crea una instancia de ConventionPack con las convenciones especificadas y, a continuación, trasládala al método ConventionRegistry.Register(), como se muestra en el siguiente ejemplo:

var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() };
ConventionRegistry.Register("CamelCaseConvention", camelCaseConvention, t => true);

Se puede mejorar el rendimiento de la aplicación representando arreglos de primitivas como estructuras de Memory<T> y ReadOnlyMemory<T> en lugar de utilizar tipos como los arreglos estándar de C# o los objetos BsonArray. El driver implementa rutas rápidas de serialización y deserialización para Memory<T> y ReadOnlyMemory<T>, lo que mejora la velocidad y reduce el uso de memoria.

Nota

Las verificaciones de truncamiento y desbordamiento no son compatibles con Memory<T> o ReadOnlyMemory<T>, pero estas verificaciones se implementan para arreglos estándar.

Puedes lograr estas mejoras de rendimiento almacenando los siguientes tipos primitivos en estructuras de Memory<T> o ReadOnlyMemory<T>:

  • bool

  • sbyte

  • byte

  • char

  • short

  • ushort

  • int

  • uint

  • long

  • ulong

  • float

  • double

  • decimal

El siguiente ejemplo define un POCO Line que contiene campos de arreglo modelados por estructuras Memory y ReadOnlyMemory:

public class Line
{
public ObjectId Id { get; set; }
public Memory<int> X { get; set; }
public ReadOnlyMemory<float> Y { get; set; }
}

El siguiente documento representa cómo se representa un objeto Line de muestra en MongoDB:

{
"_id": ...,
"X": [ 1, 2, 3, 4, 5 ],
"Y": [ 1, 1.409999966621399, 1.7300000190734863, 2, 2.240000009536743 ]
}

Tip

Vectores modelo

Para ejecutar un query de búsqueda vectorial de MongoDB, se deben crear y consultar grandes arreglos numéricos. Si la aplicación utiliza la búsqueda vectorial de MongoDB, se pueden aprovechar las mejoras de rendimiento que utilizan Memory y ReadOnlyMemory para almacenar representaciones de arreglos de incrustaciones y vectores query. Para obtener más información, consulta Tipos de incrustación de vectores admitidos en la guía de búsqueda vectorial de MongoDB.

Para aprender más sobre el uso del driver .NET/C# para serializar objetos de C#, consulta las siguientes páginas:

Para aprender más sobre cualquiera de los métodos o tipos analizados en esta guía, consulta la siguiente documentación de API:

Volver

Proxy SOCKS5

En esta página