.NET 可序列化实体

发布于 2024-11-15 11:00:38 字数 462 浏览 3 评论 0原文

我需要使所有实体可序列化。所以我在考虑使用具有备份和恢复方法的 BaseEntity。但在恢复中,我无法用保存的对象覆盖该对象,因为 this 是只读的。

有什么解决方案或其他方法来获取可序列化的实体吗?

我的代码:

internal class BaseEntity
{
    private MemoryStream ms = new MemoryStream();
    private BinaryFormatter bf = new BinaryFormatter();

    public void Backup()
    {
        bf.Serialize(ms, this);
    }

    public void Restore()
    {
        this = (BaseEntity)bf.Deserialize(ms);
    }
}

I need to make all my entities serializable. So I was thinking in a BaseEntity with a Backup and a Restore method. But in the restore I can't override the object with the saved one because this is read-only.

Any solution or some other way to get the serializable entities?

My code:

internal class BaseEntity
{
    private MemoryStream ms = new MemoryStream();
    private BinaryFormatter bf = new BinaryFormatter();

    public void Backup()
    {
        bf.Serialize(ms, this);
    }

    public void Restore()
    {
        this = (BaseEntity)bf.Deserialize(ms);
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

笑红尘 2024-11-22 11:00:38

更常见的模式是不让对象负责序列化/反序列化自身;相反,使用外部序列化器:

var serializer = new DataContractJsonSerializer(typeof(YourClass));
var stream = ...;
YourClass yourObj = ...;

serializer.WriteObject(stream, yourObj);

var restoredObj = serializer.ReadObject(stream);

The more common pattern is to not make it the responsibility of your objects to serialize/deserialize themselves; rather, use an external serializer:

var serializer = new DataContractJsonSerializer(typeof(YourClass));
var stream = ...;
YourClass yourObj = ...;

serializer.WriteObject(stream, yourObj);

var restoredObj = serializer.ReadObject(stream);
和我恋爱吧 2024-11-22 11:00:38

编辑:序列化的一种工作方式是使用 System.Runtime.Serialization.Formatters.Binary.BinaryFormatter (或 IFormatter 的其他实现)。要序列化对象,您需要传递对象和流。要反序列化对象,您传递一个流(位于序列化数据的开头),它返回序列化对象及其所有依赖项。

public static class EntityBackupServices
{
   public static MemoryStream Backup (BaseEntity entity)
   {
      var ms = new MemoryStream();
      Serialize (ms, entity);
      ms.Position = 0;
      return ms;
   }
   public static void Serialize (Stream stream, BaseEntity entity)
   {
      var binaryFormatter = new BinaryFormatter();
      binaryFormatter.Serialize (stream, entity);
   }
   public static BaseEntity Restore (Stream stream)
   {
      var binaryFormatter = new BinaryFormatter();
      var entity = (BaseEntity) binaryFormatter.Deserialize (stream);
      return entity;
   }
}

格式化程序不做的一件事(尽管 FormatterServices 类使之成为可能)是修改现有对象。因此,您可能不希望有一个名为 Deserialize 的实例方法。您实际上不能这样做:new LionEntity().Deserialize (),它会替换现有实例的字段。

注意:您需要将Serialized< /a> 覆盖所有类型。任何无法序列化的字段(因为它不是结构体,或者未标记为 [Serializable])都需要用 非序列化

// A test object that needs to be serialized.
[Serializable()]        
public class BaseEntity
{
    public int member1;
    public string member2;
    public string member3;
    public double member4;

    // A field that is not serialized.
    [NonSerialized()] public MyRuntimeType memberThatIsNotSerializable; 

    public TestSimpleObject()
    {
        member1 = 11;
        member2 = "hello";
        member3 = "hello";
        member4 = 3.14159265;
        memberThatIsNotSerializable = new Form ();
    }

    public MemoryStream Backup ()
    {
       return EntityBackupServices.Backup (this);
    }
}

编辑:
我提到的方式是一种相当标准且被接受的方式。如果您想冒险进入 hackdom,您可以按照我提到的方式反序列化对象,然后使用反射将现有对象上的每个字段设置为反序列化对象的值。

public class BaseEntity
{
   void Restore(Stream stream)
   {
      object deserialized = EntityBackupServices.RestoreDeserialize(stream);//As listed above
      if (deserialized.GetType () != this.GetType ())
         throw new Exception();
      foreach (FieldInfo fi in GetType().GetFields())
      {
         fi.SetValue(this, fi.GetValue (deserialized));
      }
   }
}

Edit: One way serialization can work is to use the System.Runtime.Serialization.Formatters.Binary.BinaryFormatter (or other implementation of IFormatter). To serialize an object you pass the object and a stream. To Deserialize the object, you pass a stream (positioned at the begining of your serialized data), and it returns the serialized object and all its depenedencies.

public static class EntityBackupServices
{
   public static MemoryStream Backup (BaseEntity entity)
   {
      var ms = new MemoryStream();
      Serialize (ms, entity);
      ms.Position = 0;
      return ms;
   }
   public static void Serialize (Stream stream, BaseEntity entity)
   {
      var binaryFormatter = new BinaryFormatter();
      binaryFormatter.Serialize (stream, entity);
   }
   public static BaseEntity Restore (Stream stream)
   {
      var binaryFormatter = new BinaryFormatter();
      var entity = (BaseEntity) binaryFormatter.Deserialize (stream);
      return entity;
   }
}

One thing a formatter don't do (though the FormatterServices class makes it possible) is modify existing objects. So you probably don't want to have an instance method called Deserialize. You can't really do this: new LionEntity().Deserialize () where it replaces the fields of an existing instance.

Note: You'll need to put Serializable over all your types. Any fields that can't be serialized (because it's either not a struct, or it's not marked as [Serializable] will need to be marked with NonSerialized.

// A test object that needs to be serialized.
[Serializable()]        
public class BaseEntity
{
    public int member1;
    public string member2;
    public string member3;
    public double member4;

    // A field that is not serialized.
    [NonSerialized()] public MyRuntimeType memberThatIsNotSerializable; 

    public TestSimpleObject()
    {
        member1 = 11;
        member2 = "hello";
        member3 = "hello";
        member4 = 3.14159265;
        memberThatIsNotSerializable = new Form ();
    }

    public MemoryStream Backup ()
    {
       return EntityBackupServices.Backup (this);
    }
}

Edit:
The way I've mentioned is a rather standard and accepted way. If you want to venture into hackdom, you can deserialize the object the way I've mentioned, then use reflection to set each field on your existing object to the value of the deserialized object.

public class BaseEntity
{
   void Restore(Stream stream)
   {
      object deserialized = EntityBackupServices.RestoreDeserialize(stream);//As listed above
      if (deserialized.GetType () != this.GetType ())
         throw new Exception();
      foreach (FieldInfo fi in GetType().GetFields())
      {
         fi.SetValue(this, fi.GetValue (deserialized));
      }
   }
}
油饼 2024-11-22 11:00:38
public IEntidadBase Restore()
{
    return (IEntidadBase)bf.Deserialize(ms);
}

@jacklondon 你会如何做 EntitySerializer 方法?

您可以使用 http://www.servicestack.net/ StackService.Text 模块对干净实体进行序列化过程。您不需要以 ms 方式使用任何属性(可序列化/数据契约)。

 public class EntityFoo
    {
        public string Bar { get; set; }

        public EntityFoo (string bar)
        {
            Bar = bar;
        }
    }

    public class EntityDumper //and the EntitySerializer
    {
        public static string Dump<T> (T entity)
        {
            return new TypeSerializer<T> ().SerializeToString (entity);
        }

        public static T LoadBack<T> (string dump)
        {
            return new TypeSerializer<T> ().DeserializeFromString (dump);
        }
    }



    public class dump_usage
    {
        public void start ()
        {
            string dump = EntityDumper.Dump (new EntityFoo ("Space"));

            EntityFoo loaded = EntityDumper.LoadBack<EntityFoo> (dump);
            Debug.Assert (loaded.Bar == "Space");
        }
    }
public IEntidadBase Restore()
{
    return (IEntidadBase)bf.Deserialize(ms);
}

@jacklondon how would you do EntitySerializer methods?

You can do serialization process with http://www.servicestack.net/ StackService.Text module for clean entities. You don't need any attribute (serializable/datacontract) in ms way.

 public class EntityFoo
    {
        public string Bar { get; set; }

        public EntityFoo (string bar)
        {
            Bar = bar;
        }
    }

    public class EntityDumper //and the EntitySerializer
    {
        public static string Dump<T> (T entity)
        {
            return new TypeSerializer<T> ().SerializeToString (entity);
        }

        public static T LoadBack<T> (string dump)
        {
            return new TypeSerializer<T> ().DeserializeFromString (dump);
        }
    }



    public class dump_usage
    {
        public void start ()
        {
            string dump = EntityDumper.Dump (new EntityFoo ("Space"));

            EntityFoo loaded = EntityDumper.LoadBack<EntityFoo> (dump);
            Debug.Assert (loaded.Bar == "Space");
        }
    }
嘿咻 2024-11-22 11:00:38

我不一定推荐这样做,但这是一种对象模式,可以使用创建新实例的序列化来持久保存和恢复其自身状态:

public sealed class MyClass
{
    private Data _data = new Data();

    //Properties go here (access the public fields on _data)

    public void Backup()
    {
        //Serialize Data
    }

    public void Restore()
    {
        //Deserialize Data and set new instance
    }

    private sealed class Data
    {
        //Public fields go here (they're private externally [because Data is private], but public to MyClass.)
    }
}

请注意,只有当您的序列化程序支持非公共类时,这才有效。最坏的情况是,您必须将嵌套类设为公共,这很丑陋,但不会损害封装(因为实例是私有的)。

I don't necessarily recommend this, but here is one pattern for an object that can persist and restore its own state using serialization that creates new instances:

public sealed class MyClass
{
    private Data _data = new Data();

    //Properties go here (access the public fields on _data)

    public void Backup()
    {
        //Serialize Data
    }

    public void Restore()
    {
        //Deserialize Data and set new instance
    }

    private sealed class Data
    {
        //Public fields go here (they're private externally [because Data is private], but public to MyClass.)
    }
}

Note that this only works if your serializer supports non-public classes. Worst-case, you have to make the nested class public, which is ugly, but doesn't hurt encapsulation (since the instance is private).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文