存储和序列化任意类

时间:2016-06-24 20:48:13

标签: c# serialization

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

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>中,然后引用它。然而,这对我来说有点蠢,让我想知道我是否完全做错了。存储和序列化类的一些尝试和真实的方法是什么?

2 个答案:

答案 0 :(得分:1)

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

使用任一方法都可以避免为存储创建单独的类,并且.NET Framework完全支持它。

答案 1 :(得分:0)

在经历了一些困难之后,我决定使用反射来简单地按字段匹配字段。这样我需要做的就是创建一个我想要保存在存储类中的字段。我也不需要进行任何手动分配,因此我的项目规模看起来相当可持续。以下是两种方法。

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;
}