A menudo uso este enfoque en mi propio juego C # / .NET. Además de los otros beneficios (¡y riesgos!) Descritos aquí, también puede ayudar a evitar problemas de serialización.
Si desea aprovechar las funciones de serialización binaria incorporadas en .NET Framework, el uso de ID de entidad puede ayudar a minimizar el tamaño del gráfico de objeto que se escribe. Por defecto, el formateador binario de .NET serializará un gráfico de objeto completo a nivel de campo. Digamos que quiero serializar una Ship
instancia. Si Ship
tiene un _owner
campo que hace referencia al Player
propietario, entonces esa Player
instancia también se serializaría. Si Player
contiene un _ships
campo (de, digamos, ICollection<Ship>
), todas las naves del jugador también se escribirán, junto con cualquier otro objeto referenciado en el nivel del campo (recursivamente). Es fácil serializar accidentalmente un gran gráfico de objetos cuando solo desea serializar una pequeña parte de él.
Si, en cambio, tengo un _ownerId
campo, entonces puedo usar ese valor para resolver la Player
referencia a pedido. Mi API pública incluso puede permanecer sin cambios, con la Owner
propiedad simplemente realizando la búsqueda.
Si bien las búsquedas basadas en hash son generalmente muy rápidas, la sobrecarga adicional podría convertirse en un problema para conjuntos de entidades muy grandes con búsquedas frecuentes. Si se convierte en un problema para usted, puede almacenar en caché la referencia utilizando un campo que no se serializa. Por ejemplo, podría hacer algo como esto:
public class Ship
{
private int _ownerId;
[NonSerialized] private Lazy<Player> _owner;
public Player Owner
{
get { return _owner.Value; }
}
public Ship(Player owner)
{
_ownerId = owner.PlayerID;
EnsureCache();
}
private void EnsureCache()
{
if (_owner == null)
_owner = new Lazy<Player>(() => Game.Current.Players[_ownerId]);
}
[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
EnsureCache();
}
}
Por supuesto, este enfoque también puede hacer que la serialización más difícil cuando realmente se desea serializar un gráfico de objetos de gran tamaño. En esos casos, necesitaría idear algún tipo de 'contenedor' para garantizar que se incluyan todos los objetos necesarios.