In Protobuf-net how can I pass an array of type object with objects of different types inside, knowing the set of potential types in advance

后端 未结 1 1825
青春惊慌失措
青春惊慌失措 2020-12-03 16:06

I am trying to migrate existing code that uses XmlSerializer to protobuf-net due to the increased performance it offers, however I am having problems with this specific case

相关标签:
1条回答
  • 2020-12-03 16:50

    object is going to be problematic. I would try something more like:

    [ProtoContract]
    class Message
    {
        private readonly List<MessageParam> parameters = new List<MessageParam>();
        [ProtoMember(1)]
        public List<MessageParam> Parameters { get { return parameters; } }
    }
    [ProtoContract]
    [ProtoInclude(3, typeof(MessageParam<int>))]
    [ProtoInclude(4, typeof(MessageParam<float>))]
    [ProtoInclude(5, typeof(MessageParam<DateTime>))]
    //...known types...
    abstract class MessageParam {
        public abstract object UntypedValue { get; set; }
        public static MessageParam<T> Create<T>(T value) {
            return new MessageParam<T> { Value = value };
        }
        public static MessageParam CreateDynamic(object value)
        {
            Type type = value.GetType();
            switch (Type.GetTypeCode(value.GetType()))
            {
                // special cases
                case TypeCode.Int32: return Create((int)value);
                case TypeCode.Single: return Create((float)value);
                case TypeCode.DateTime: return Create((DateTime)value);
                // fallback in case we forget to add one, or it isn't a TypeCode
                default:
                    MessageParam param = (MessageParam)Activator.CreateInstance(
                        typeof(MessageParam<>).MakeGenericType(type));
                    param.UntypedValue = value;
                    return param;
            }
        }
    }
    [ProtoContract]
    sealed class MessageParam<T> : MessageParam
    {
        [ProtoMember(1)]
        public T Value { get; set; }
        public override object UntypedValue
        {
            get { return Value; }
            set { Value = (T)value; }
        }
    }
    

    Note that the unreleased "v2" code offers much more ability to define the relationships at runtime rather than through attributes (which is quite limiting here).

    0 讨论(0)
提交回复
热议问题