Mirror of Svelto.ECS because we're a fan of it
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

102 lines
3.7KB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Reflection;
  4. using Svelto.ECS.Serialization;
  5. namespace Svelto.ECS
  6. {
  7. partial class EnginesRoot
  8. {
  9. sealed class SerializationDescriptorMap
  10. {
  11. /// <summary>
  12. /// Use reflection to register all the ISerializableEntityDescriptor to be used for serialization
  13. /// </summary>
  14. internal SerializationDescriptorMap()
  15. {
  16. _descriptors = new Dictionary<uint, ISerializableEntityDescriptor>();
  17. _factories = new Dictionary<uint, IDeserializationFactory>();
  18. Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
  19. foreach (Assembly assembly in assemblies)
  20. {
  21. foreach (Type type in GetTypesSafe(assembly))
  22. {
  23. if (type != null && type.IsClass && type.IsAbstract == false && type.BaseType != null && type.BaseType.IsGenericType &&
  24. type.BaseType.GetGenericTypeDefinition() == typeof(SerializableEntityDescriptor<>))
  25. {
  26. var descriptor = Activator.CreateInstance(type) as ISerializableEntityDescriptor;
  27. RegisterEntityDescriptor(descriptor);
  28. }
  29. }
  30. }
  31. }
  32. static IEnumerable<Type> GetTypesSafe(Assembly assembly)
  33. {
  34. try
  35. {
  36. Type[] types = assembly.GetTypes();
  37. return types;
  38. }
  39. catch (ReflectionTypeLoadException e)
  40. {
  41. return e.Types;
  42. }
  43. }
  44. void RegisterEntityDescriptor(ISerializableEntityDescriptor descriptor)
  45. {
  46. if (descriptor == null)
  47. {
  48. return;
  49. }
  50. uint descriptorHash = descriptor.hash;
  51. #if DEBUG && !PROFILER
  52. if (_descriptors.ContainsKey(descriptorHash))
  53. {
  54. throw new Exception($"Hash Collision of '{descriptor.GetType()}' against " +
  55. $"'{_descriptors[descriptorHash]} ::: {descriptorHash}'");
  56. }
  57. #endif
  58. _descriptors[descriptorHash] = descriptor;
  59. }
  60. public ISerializableEntityDescriptor GetDescriptorFromHash(uint descriptorID)
  61. {
  62. #if DEBUG && !PROFILER
  63. DBC.ECS.Check.Require(_descriptors.ContainsKey(descriptorID),
  64. $"Could not find descriptor with ID '{descriptorID}'!");
  65. #endif
  66. return _descriptors[descriptorID];
  67. }
  68. public IDeserializationFactory GetSerializationFactory(uint descriptorID)
  69. {
  70. return _factories.TryGetValue(descriptorID, out var factory) ? factory : null;
  71. }
  72. public void RegisterSerializationFactory<Descriptor>(IDeserializationFactory deserializationFactory)
  73. where Descriptor : ISerializableEntityDescriptor, new()
  74. {
  75. _factories.Add(SerializationEntityDescriptorTemplate<Descriptor>.hash, deserializationFactory);
  76. }
  77. readonly Dictionary<uint, ISerializableEntityDescriptor> _descriptors;
  78. readonly Dictionary<uint, IDeserializationFactory> _factories;
  79. }
  80. /// <summary>
  81. /// The map of serializable entity hashes to the serializable entity builders (to know the entity structs
  82. /// to serialize)
  83. /// </summary>
  84. SerializationDescriptorMap serializationDescriptorMap { get; }
  85. }
  86. }