.Net二进制序列化-如何限制对象图?

.Net二进制序列化-如何限制对象图?,.net,serialization,.net,Serialization,我有一个对象,我希望尽可能高效地在进程之间序列化和分发。对象本身引用了另一个对象,如下所示: public class Foo { // Unique Identifier: public int Id; public Bar Bar; } public class Bar { // Unique Identifier: public int Id; } 问题是,我只想序列化Foo并在网络上运行它。我不希望在我通过线路发送的内容中包含Bar,因为它在另

我有一个对象,我希望尽可能高效地在进程之间序列化和分发。对象本身引用了另一个对象,如下所示:

public class Foo
{
    // Unique Identifier:
    public int Id;
    public Bar Bar;
}

public class Bar
{
    // Unique Identifier:
    public int Id;
}
问题是,我只想序列化Foo并在网络上运行它。我不希望在我通过线路发送的内容中包含Bar,因为它在另一端是已知的,发送它会浪费我的“带宽”

我想做的是:

  • 在序列化时,我将序列化 引用Bar(Foo.Bar)作为 int包含:Bar.Id(这是一个 条形图实例的唯一标识符)

  • 只有Foo将通过网络发送 wire(包含int而不是 条形图属性)

  • 在反序列化时,我会得到 int,从 存储库并将其放入 Foo.Bar属性


  • 这是限制序列化对象图的有效方法吗?有更好的方法吗?

    这听起来是可行的,本质上,您可以在Foo上实现ISerializable接口,它可以让您控制如何序列化Foo


    然后您实现相应的构造函数,您将有权访问保存的状态并可以提取id。

    这听起来是可行的,实际上您在Foo上实现了ISerializable接口,它将允许您控制如何序列化Foo


    然后您实现相应的构造函数,您将有权访问保存的状态并可以提取id。

    您所描述的需要使用常规的
    二进制格式化程序
    进行ISerializable
    (自定义序列化)
    -然而,protobuf net允许您简化事情(因此您不需要自己处理细节),同时通常会在过程中缩小数据:

    [ProtoContract]
    public class Foo : ISerializable
    {
        // Unique Identifier:
        [ProtoMember(1)]
        public int Id;
        public Bar Bar;
    
        [ProtoMember(2)]
        private int? BarProxy {
            get {
               if(Bar == null) return null;
               return Bar.Id;
            }
            set {
               if(value == null) { Bar = null; }
               else { // fetch from repository
                 Bar = new Bar(); 
                 Bar.Id = value;
               }
            }
        }
    
        public Foo() { }
    
        void ISerializable.GetObjectData(SerializationInfo info,
               StreamingContext context) {
            Serializer.Serialize(info, this);
        }
        protected Foo(SerializationInfo info, StreamingContext context) {
            Serializer.Merge(info, this);
        }
    }
    
    public class Bar
    {
        // Unique Identifier:
        public int Id;
    }
    

    对于更简单的设置:

    您使用的是什么序列化程序

    • 使用
      BinaryFormatter
      ,您可以将不需要的字段标记为
      [非序列化]
    • 使用
      XmlSerializer
      ,您可以将不需要的成员标记为
      [XmlIgnore]
    • 使用
      DataContractSerializer
      ,您只需不使用
      [DataContract]

    也可以考虑;这有一个非常有效的二进制机制;比<代码> BinaryFormatter < /Cult>

    < P>您所描述的将要求<代码>可ISIALIALITION/<代码>(自定义序列化),使用常规<代码> BinaryFormatter < /C> >但是,TrimBuf网将允许您简化事情。(因此您不需要自己处理细节),同时通常会在过程中缩小数据:

    [ProtoContract]
    public class Foo : ISerializable
    {
        // Unique Identifier:
        [ProtoMember(1)]
        public int Id;
        public Bar Bar;
    
        [ProtoMember(2)]
        private int? BarProxy {
            get {
               if(Bar == null) return null;
               return Bar.Id;
            }
            set {
               if(value == null) { Bar = null; }
               else { // fetch from repository
                 Bar = new Bar(); 
                 Bar.Id = value;
               }
            }
        }
    
        public Foo() { }
    
        void ISerializable.GetObjectData(SerializationInfo info,
               StreamingContext context) {
            Serializer.Serialize(info, this);
        }
        protected Foo(SerializationInfo info, StreamingContext context) {
            Serializer.Merge(info, this);
        }
    }
    
    public class Bar
    {
        // Unique Identifier:
        public int Id;
    }
    

    对于更简单的设置:

    您使用的是什么序列化程序

    • 使用
      BinaryFormatter
      ,您可以将不需要的字段标记为
      [非序列化]
    • 使用
      XmlSerializer
      ,您可以将不需要的成员标记为
      [XmlIgnore]
    • 使用
      DataContractSerializer
      ,您只需不使用
      [DataContract]

    也可以考虑;这有一个非常有效的二进制机制;比<>代码> BinaryFormatter < /Cord>

    > p>我不确定我是否在这里漏掉了什么。

    只需在不想序列化的字段上使用
    非序列化
    属性即可

    然后,查看如何在反序列化时修复引用

    我使用类似的方法对LINQ2SQL对象进行二进制序列化

    更新:

    更好的主意(忘了这个)。使用,这很容易使用

    使用代理方法将允许您返回该对象的另一个实例(如果已经加载到内存中的话)

    更新2:


    你可以在中间看到一个ISILIALIZATIORATORATH的例子。(我为前面的丑陋道歉)。 只需在不想序列化的字段上使用

    非序列化
    属性即可

    然后,查看如何在反序列化时修复引用

    我使用类似的方法对LINQ2SQL对象进行二进制序列化

    更新:

    更好的主意(忘了这个)。使用,这很容易使用

    使用代理方法将允许您返回该对象的另一个实例(如果已经加载到内存中的话)

    更新2:


    中可以看到一个IsIILIALATION SURROGATH的例子。(我为前面的丑陋道歉)。

    好的建议,使用非序列化。一个简短的代码示例会有帮助。什么是“序列化代理”??我认为NotSerialized是解决方案的一半-如何不序列化Bar。但还有另一半需要实现-向反序列化方指示要将哪个Bar实例注入对象。为ISerializationsProgate添加了MSDN链接。设置起来有点费时,但一旦你看到了方法,就很容易了。好的建议stion,使用非序列化。一个简短的代码示例会很有帮助。“序列化代理”是什么?我认为NotSerialized是解决方案的一半-如何不序列化Bar。但还有另一半需要实现-向反序列化方指示要将哪个Bar实例注入对象。为ISerializationsProgate添加了MSDN链接。设置起来有点费时,但一旦你看到了方法,就很容易了。呵呵,我继续我注意到你已经提到了非系列化:)呵呵,我只是注意到你已经提到了非系列化:)