【问题标题】:Storing and serializing arbitrary classes存储和序列化任意类
【发布时间】:2016-06-24 20:48:12
【问题描述】:

现在我有几个类我希望序列化并保存到磁盘(格式并不重要)。但是,我真正需要存储的只是每个选项中的几个选择字段。这些字段因班级而异,但都是公开的。

public class A {
    public string stringField;
    public int intField;
    ...
}

public class B {
    public float floatField;
    public Object objectField;
    ...
}

我的方法是创建一个简单的容器类,它可以存储和序列化这些字段,并加载它们以返回该类的实例,并为每个类存储公共字段。

我可以通过为我想要存储的类中的匹配字段创建一个类来做到这一点。

public class AStorage{
    public string stringFieldStorage;
    public int intFieldStorage;
    ...

    public void StoreA(A a){
        stringFieldStorage = a.stringField;
        intFieldStorage = a.intField;
    }       

    public A GetA(){
        A a = new A();
        a.stringField = stringFieldStorage;
        a.intField = intFieldStorage;
        return a;
    }
}

这可行,但这意味着我需要很多类,并且我需要根据他们希望从他们存储的类中接收到的内容来为他们提供字段。

我研究过使用反射来获取字段和名称,这很容易。然后,我可以将它们放在由字段名称键入的Dictonary<string, Object> 中,然后引用它。然而,这让我觉得有点恶心,让我想知道我是否完全做错了事。存储和序列化类的一些经过验证且真实的方法是什么?

【问题讨论】:

    标签: c# serialization


    【解决方案1】:

    许多序列化程序支持selective serialization,例如通过标记不应使用 NotSerializedAttribute 序列化的属性(例如二进制序列化程序)或通过要求属性显式选择序列化,例如DataContractSerializer 的 DataMemberAttribute。

    使用任何一种方法都可以避免创建单独的存储类,并且 .NET Framework 开箱即用地完全支持。

    【讨论】:

      【解决方案2】:

      经过一番折腾后,我决定使用反射来简单地按名称匹配字段。这样,我需要做的就是创建一个我想保存在存储类中的字段。我也不需要进行任何手动分配,因此对于我的项目规模来说它看起来相当可持续。这是两种方法。

      public void Store(Object source){
          var thisType = this.GetType ();
          var sourceFields = source.GetType ().GetFields (flags);
          foreach (var field in sourceFields) { //get all properties via reflection
              var instanceField = thisType.GetField (field.Name);
              if(instanceField != null){ //check if this instance has the source's property
                  var value = field.GetValue(source); //get the value from the object
                  if(value != null){
                      instanceField.SetValue(this, value); //put it into this instance
                  }
              }
          }
      }
      
      public T LoadIntoObject<T> (T target){
          var targetFields = target.GetType().GetFields ();
          foreach (var field in targetFields) {
              var instanceField = this.GetType().GetField (field.Name);
              if(instanceField != null){ //check if this instance has the targets's property
                  var value = instanceField.GetValue(this);
                  if(value != null){
                      field.SetValue(target, value); //put it into the target
                  }
              }
          }
          return target;
      }
      

      【讨论】:

      • 序列化是.NET Framework很好解决的问题。为什么要创建自己的解决方案?
      猜你喜欢
      • 2011-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-07
      • 1970-01-01
      • 2017-05-22
      • 1970-01-01
      相关资源
      最近更新 更多