使用 MessagePack 进行涉及继承的序列化后反射不正确

Incorrect reflection after inheritance-involved serialization with MessagePack

我正在服务器上序列化一个 Entity

    public class Entity
    {
        private List<Component> _components = new List<Component>();
        [Key(0)]
        public List<Component> Components {
            get {
                return _components;
            }
            set
            {
                _components = value;
            }
        }

        public T GetComponent<T>() where T : Component
        {
            foreach (Component component in _components)
            {
                var componentType = component.GetType();
                Debug.WriteLine(componentType);
                if (componentType.Equals(typeof(T)))
                {
                    return (T)component;
                }
            }
            return null;
        }
    }

    [MessagePackObject]
    public class Component
    {
        [IgnoreMember]
        public Entity entity;
    }

    [MessagePackObject]
    public class Tile : Component
    {
        public enum TileType
        {
            Soil,
            Mud,
        }

        [Key(0)]
        public TileType Type { get; set; }

        public Tile(TileType type)
        {
            Type = type;
        }
    }

每个 Entity 都有一个 Tile(继承自 Component)。在序列化之前,我检查了 Tile 的类型,它 returns World2D.ECS.Components.Tile.

然后我将序列化的 Entity 发送给客户。

在客户端我检查组件的反射类型:

public T GetComponent<T>() where T : Component
        {
            foreach (Component component in _components)
            {
                var componentType = component.GetType();
                Debug.WriteLine(componentType); // returns World2D.ECS.Components.Component instead of World2D.ECS.Components.Tile as on the server
                if (componentType.Equals(typeof(T)))
                {
                    return (T)component;
                }
            }
            return null;
        }

在客户端反序列化 Entity 后,反射 returns World2D.ECS.Components.Component 而不是 World2D.ECS.Components.Tile.

更新 1:确认这不会由于通过网络发送序列化 Entity 而发生,因为即使在同一台机器上序列化和反序列化也会出现错误。

https://github.com/neuecc/MessagePack-CSharp/issues/1405

By default, type information is not included in the messagepack stream. The best way to add type information is to apply the [Union] attribute as described in the readme. You might also find the Typeless resolver can solve your problem, but that comes with security implications and a larger data size.