【问题标题】:Protobuf-net null/empty lists and reference equalityProtobuf-net 空/空列表和引用相等
【发布时间】:2011-11-21 20:48:52
【问题描述】:

如何配置 protobuf-net 类型模型以通过以下示例中的 3 个单元测试? Protobuf 版本是 v2 r470。

我已经简要地查看了 svn 树中的列表测试,但无法发现这与 protobuf-net svn 中的空测试与空测试之间的区别。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using ProtoBuf; 
using ProtoBuf.Meta;

namespace ProtoCollections
{ 
   [TestFixture]
   public class CollectionTests
   {
      [Test]
      public void TestEmptyList()
      {
         var model = TypeModel.Create();

         var orig = new TypeWithReferenceList(Enumerable.Empty<SomeReferenceType>());         
         var clone = (TypeWithReferenceList)model.DeepClone(orig);
         Assert.IsNotNull(clone.List);
         Assert.IsEmpty(clone.List);         
      }

      [Test]
      public void TestNullList()
      {
         var model = TypeModel.Create();
         var orig = new TypeWithReferenceList(null);         
         var clone = (TypeWithReferenceList)model.DeepClone(orig);
         Assert.IsNull(clone.List);
      }

      [Test]
      public void TestList()
      {
         var model = TypeModel.Create();
         model[typeof (SomeReferenceType)].AsReferenceDefault = true;

         SomeReferenceType repeatedItem = new SomeReferenceType(123);
         var orig = new TypeWithReferenceList(new []{repeatedItem, repeatedItem});
         var clone = (TypeWithReferenceList)model.DeepClone(orig);

         Assert.AreEqual(orig.List.Count, clone.List.Count);
         Assert.AreSame(orig.List[0], orig.List[1]);

         Assert.AreEqual(orig.List[0].Value, clone.List[0].Value);
         Assert.AreSame(clone.List[0], clone.List[1]);            
      }
   }

   [ProtoContract(ImplicitFields = ImplicitFields.AllFields, SkipConstructor = true)]
   public class SomeReferenceType
   {
      private int value;
      public SomeReferenceType(int val)
      {
         value = val;
      }
      public int Value { get { return value; } }
   }

   [ProtoContract(ImplicitFields = ImplicitFields.AllFields, SkipConstructor = true)]
   public class TypeWithReferenceList
   {
      private List<SomeReferenceType> innerList;

      public TypeWithReferenceList(IEnumerable<SomeReferenceType> items)
      {
         innerList = items == null ? null : items.ToList();
      }

      public List<SomeReferenceType> List { get { return innerList; } }
   }

}

【问题讨论】:

    标签: .net serialization protobuf-net


    【解决方案1】:

    第三个似乎是将AsReferenceDefault 应用于隐式字段的故障;它看起来像手动装饰成员(使用AsReference=true),就像在运行时应用它一样:

    model[typeof(TypeWithReferenceList)][1].AsReference = true;
    

    我会调查为什么会这样。

    由于 protobuf 默认跳过空值的方式,第二个已经过去了。

    第一个更棘手 - 再次,由于谷歌规范没有 null 的概念,这是......有问题的。目前可以用一些令人讨厌的假属性来欺骗它,但并不理想。就个人而言,我会说“保持简单;使集合始终不为空”(通常通过字段初始化程序或反序列化回调)。最近允许空值 inside 列表的更改也可以扩展为支持显式空值 outside 列表(在选择加入的基础上)。

    然而,这里的问题似乎是你希望它表现得像BinaryFormatter。但是,它不是BinaryFormatter。它不是作为BinaryFormatter 的直接替代品而设计的(尽管它可以很好地替代XmlSerializerDataContractSerializer,它们具有更相似的语义)。底层有线格式最终具有局限性 - 这是由 Google 设计的有线格式的体现,它高效且相当无包袱。

    特别是,在处理大多数 DTO 模型和目标场景时,这些“限制”中的大多数都不会出现。

    【讨论】:

    • 谢谢马克。是的,正如您所建议的,我正在尝试替换大型 BinaryFormatter 场景(1000 个域对象,没有特殊的 DTO 对象)。我可以尝试通过例如调整模型确保集合不为空等,但在我冒险尝试之前,我只想了解一下参照完整性位的工作原理,即是否有一些展示者,如果有,他们的问题编号是什么。
    猜你喜欢
    • 1970-01-01
    • 2011-01-23
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多