C#-使用内部/受保护的var和非空构造函数进行序列化

时间:2019-01-30 09:29:34

标签: c# serialization deserialization

有点背景:我正在某个规模较大的项目中实现序列化,该项目将数据保存到一个文件或多个文件中。虽然我不是一个人在项目中,但我是唯一拥有序列化经验的人,尽管显然不足以自己解决这个问题。

目标是创建一个类库,以便我们可以实现MVVM并允许在考虑跨平台的情况下轻松进行开发。这意味着所有未公开的类都必须是内部的。而且,某些数据被赋予了受保护的或专用的setter,以防止即使在类库中也不应该发生的突变。更为复杂的是,某些类的基类带有非默认构造函数,这些构造函数会初始化使用的字段,并且不能为null或默认值(对于不可为null的类型)。这些通常是初始化只读字段。

对于任何可访问性级别,我都需要能够选择性地序列化数据,还需要调用任何基本构造函数并为其提供正确的参数。

我尝试过:BinaryFormatterDataContractSerializerXmlSerializer
我对DataContractSerializer的运气最大,因为它允许具有非公共get /属性的设置为可以很好地序列化,并且像BinaryFormatter那样选择加入而不是选择退出。问题在于,它们每个都提供了一种自动的序列化方法-无需调用构造函数。
我知道OnSerializing / OnDeserializing / OnDeserialized / OnSerialized属性。不幸的是,它们无法设置只读属性或调用基本构造函数。

我以前也用空的构造函数实现了我的类的“ Serializer”版本,然后可以将其传递给实际的类构造函数,虽然它起作用,但它很繁琐,并且需要大量重写相同的代码,才可以强制执行构造函数,更不用说额外的内存使用了。

我还尝试过使用ISerializable,它允许我强制使用构造函数,该函数允许我调用基本构造函数并在必要时提供必要的值。但是,它没有使用使Serialize / DataMember属性实际有用的默认序列化。

我认为我使用反射和自定义属性有一个聪明的解决方法:

protected SerializeClassDemo(SerializationInfo info, StreamingContext context)
{
    List<PropertyInfo> propertySaveables = saveableProperties();
    foreach (PropertyInfo saveable in propertySaveables)
    {
        saveable.SetValue(this, info.GetValue(saveable.Name, saveable.PropertyType));
    }
    List<FieldInfo> fieldSaveables = saveableFields();
    foreach (FieldInfo saveable in fieldSaveables)
    {
        saveable.SetValue(this, info.GetValue(saveable.Name, saveable.FieldType));
    }
}

[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
    List<PropertyInfo> propertySaveables = saveableProperties();
    foreach (PropertyInfo saveable in propertySaveables)
    {
        info.AddValue(saveable.Name, saveable.GetValue(this), saveable.PropertyType);
    }
    List<FieldInfo> fieldSaveables = saveableFields();
    foreach (FieldInfo saveable in fieldSaveables)
    {
        info.AddValue(saveable.Name, saveable.GetValue(this), saveable.FieldType);
    }
}

private List<PropertyInfo> saveableProperties()
{
    List<PropertyInfo> saveables = new List<PropertyInfo>();
    PropertyInfo[] props = typeof(SerializeClassDemo).GetProperties();
    foreach (PropertyInfo prop in props)
    {
        SaveAttribute attrs = prop.GetCustomAttribute<SaveAttribute>();
        if (attrs != null)
        {
            saveables.Add(prop);
        }
    }
    return saveables;
}

private List<FieldInfo> saveableFields()
{
    List<FieldInfo> saveables = new List<FieldInfo>();
    FieldInfo[] fields = typeof(SerializeClassDemo).GetFields();
    foreach (FieldInfo field in fields)
    {
        SaveAttribute attrs = field.GetCustomAttribute<SaveAttribute>();
        if (attrs != null)
        {
            saveables.Add(field);
        }
    }
    return saveables;
}

这将像默认的XmlSerialization一样自动序列化和反序列化数据,但是我使用反射的方式仅适用于公共成员。

在这一点上,我已经意识到,虽然我最终可能会偶然浏览足够多的文档页面以找到理想的解决方案,但我可能会节省时间和精力,只是询问-是否有一种相对简单的序列化方法/反序列化数据,以便与内部/受保护的数据一起使用,并允许我满足需要参数的基本构造函数的需求?

编辑:该项目将是免费的,并且该项目的许可证为GPL-3,它满足使用任何提供的代码的堆栈溢出的创用CC要求。我不会从提供的任何帮助中赚钱。欢呼。

0 个答案:

没有答案