vhson / protobuf-net

Automatically exported from code.google.com/p/protobuf-net
Other
0 stars 0 forks source link

TypeModel. CanSerialize(Type type, bool allowBasic, bool allowContract, bool allowLists) wrong result for complex dictionary type #408

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Please include an e-mail address if this might need a dialogue!
==============

What steps will reproduce the problem?
1. I have class with [Serializable] attribute named CarBase

    [Serializable]
    public class CarBase
    {
        public int Id { get; set; }

        public string Name { get; set; }

    }

2. I have method return a dictionary type with Dictionary<string,List<CarBase>>

3. Normally the generic type Dictionary<string,List<CarBase>> call with 
TypeModel. CanSerialize it should return false.

4.ProtoBuf.Caching.Enyim.NetTranscoder line 119 use this method to judge 
whether use default transcoder or protobuff, but is return true, then go to 
Line 125  model.Serialize(ms, o) to serialize the object ,it return a error 
with the detailed stack trace :

2013-09-24 13:51:49,832 [7] ERROR Enyim.Caching.MemcachedClient [(null)] - 
System.InvalidOperationException: No serializer defined for type: 
BitAuto.Reviews.Models.CarBase
   在 ProtoBuf.Serializers.TupleSerializer..ctor(RuntimeTypeModel model, ConstructorInfo ctor, MemberInfo[] members) 位置 E:\tfs-source\bitauto\A3车型产品研发\点评\Src\BitAutoReviews.V4\plugins\protobuf-net\protobuf-net\Serializers\TupleSerializer.cs:行号 50
   在 ProtoBuf.Meta.MetaType.BuildSerializer() 位置 E:\tfs-source\bitauto\A3车型产品研发\点评\Src\BitAutoReviews.V4\plugins\protobuf-net\protobuf-net\Meta\MetaType.cs:行号 439
   在 ProtoBuf.Meta.MetaType.get_Serializer() 位置 E:\tfs-source\bitauto\A3车型产品研发\点评\Src\BitAutoReviews.V4\plugins\protobuf-net\protobuf-net\Meta\MetaType.cs:行号 384
   在 ProtoBuf.Meta.RuntimeTypeModel.Serialize(Int32 key, Object value, ProtoWriter dest) 位置 E:\tfs-source\bitauto\A3车型产品研发\点评\Src\BitAutoReviews.V4\plugins\protobuf-net\protobuf-net\Meta\RuntimeTypeModel.cs:行号 752
   在 ProtoBuf.Meta.TypeModel.TrySerializeAuxiliaryType(ProtoWriter writer, Type type, DataFormat format, Int32 tag, Object value, Boolean isInsideList) 位置 E:\tfs-source\bitauto\A3车型产品研发\点评\Src\BitAutoReviews.V4\plugins\protobuf-net\protobuf-net\Meta\TypeModel.cs:行号 124
   在 ProtoBuf.Meta.TypeModel.TrySerializeAuxiliaryType(ProtoWriter writer, Type type, DataFormat format, Int32 tag, Object value, Boolean isInsideList) 位置 E:\tfs-source\bitauto\A3车型产品研发\点评\Src\BitAutoReviews.V4\plugins\protobuf-net\protobuf-net\Meta\TypeModel.cs:行号 170
   在 ProtoBuf.Meta.TypeModel.SerializeCore(ProtoWriter writer, Object value) 位置 E:\tfs-source\bitauto\A3车型产品研发\点评\Src\BitAutoReviews.V4\plugins\protobuf-net\protobuf-net\Meta\TypeModel.cs:行号 188
   在 ProtoBuf.Meta.TypeModel.Serialize(Stream dest, Object value, SerializationContext context) 位置 E:\tfs-source\bitauto\A3车型产品研发\点评\Src\BitAutoReviews.V4\plugins\protobuf-net\protobuf-net\Meta\TypeModel.cs:行号 217
   在 ProtoBuf.Meta.TypeModel.Serialize(Stream dest, Object value) 位置 E:\tfs-source\bitauto\A3车型产品研发\点评\Src\BitAutoReviews.V4\plugins\protobuf-net\protobuf-net\Meta\TypeModel.cs:行号 201
   在 ProtoBuf.Caching.Enyim.NetTranscoder.Enyim.Caching.Memcached.ITranscoder.Serialize(Object o) 位置 E:\tfs-source\bitauto\A3车型产品研发\点评\Src\BitAutoReviews.V4\protobuf-net.Enyim\ProtoTranscoder.cs:行号 125

What is the expected output? What do you see instead?
I think there is something wrong with generice type of complex dictionary type 
, it should use the inner Transcoder .

What version of the product are you using? On what operating system?

Please provide any additional information below.

Original issue reported on code.google.com by liurongw...@gmail.com on 24 Sep 2013 at 6:21

GoogleCodeExporter commented 9 years ago
        NetTranscoder.cs I fixed it use this method ,now it can work correctly.

        private bool CanSerializeContractType(Type type)
        {
            if (type.IsGenericType)
            {
                var paraTypes = type.GetGenericArguments();

                if (paraTypes.Count() > 0)
                {
                    var canTypesSerialized = paraTypes.Select(x => CanSerializeContractType(x));

                    return canTypesSerialized.All(x => x);
                }
                else
                {
                    return model.CanSerializeContractType(type);
                }
            }

            return model.CanSerialize(type);
        }

Original comment by liurongw...@gmail.com on 27 Sep 2013 at 3:53