在C#中,在将对象序列化到文件之后,如何在不创建新对象的情况下将文件反序列化为现有对象?

我可以找到的自定义序列化的所有示例都涉及实现一个将在反序列化时调用的构造函数,这正是我想要的,除了我不希望函数成为构造函数。

谢谢!

===============>>#1 票数:7

一些序列化程序支持回调; 例如, BinaryFormatterDataContractSerializer (以及下面的protobuf-net)允许您指定before-serializaton回调,并且由于它们跳过构造函数,这可能足以初始化对象。 但是,序列化程序仍在创建它。


大多数序列化程序都想要自己创建新对象,但有些序列化程序允许您反序列化为现有对象。 嗯,实际上唯一一个跳跃到脑海的人是protobuf-net(披露:我是作者)......

这有两个不同的功能可能会有所帮助; 对于对象(即图中最外面的对象),您可以将现有对象直接提供给Merge方法(在v1中,在v2中也是为了兼容性),或者在(在v2中)提供Deserialize方法; 例如:

var obj = Serializer.Merge<YourType>(source, instance);

但是,在较大的图形中,您可能希望自己提供其他对象(而不仅仅是根目录)。 以下内容未在属性 API中公开,但是是v2中的新功能:

RuntimeTypeModel.Default[typeof(SomeType)].SetFactory(factoryMethod);

其中factoryMethod可以是任一的名称 static在方法SomeType (即返回一个SomeType实例),或者可以是MethodInfo任何static方法的任何地方。 如果需要,该方法还可以(可选)将序列化上下文作为参数。 然后,此方法应用于提供SomeType所有新实例。


注意:protobuf-net与BinaryFormatter 完全相同; 为了获得最佳效果,您需要告诉它如何映射您的成员 - 非常类似于将事物标记为WCF / DataContractSerializer的[DataMember] 可以是属性,但不是必须的。

===============>>#2 票数:5

没问题,只需使用2个班级。 在getObject方法中,您将获得现有对象

[Serializable]
public class McRealObjectHelper : IObjectReference, ISerializable 
{
    Object m_realObject;
    virtual object getObject(McObjectId id)
    {
        return id.GetObject();
    }
    public McRealObjectHelper(SerializationInfo info, StreamingContext context)
    {
        McObjectId id = (McObjectId)info.GetValue("ID", typeof(McObjectId));
        m_realObject = getObject(id);
        if(m_realObject == null)
            return;
        Type t = m_realObject.GetType();
        MemberInfo[] members = FormatterServices.GetSerializableMembers(t, context);
        List<MemberInfo> deserializeMembers = new List<MemberInfo>(members.Length);
        List<object> data = new List<object>(members.Length);
        foreach(MemberInfo mi in members)
        {
            Type dataType = null;
            if(mi.MemberType == MemberTypes.Field)
            {
                FieldInfo fi = mi as FieldInfo;
                dataType = fi.FieldType;
            } else if(mi.MemberType == MemberTypes.Property){
                PropertyInfo pi = mi as PropertyInfo;
                dataType = pi.PropertyType;
            }
            try
            {
                if(dataType != null){
                    data.Add(info.GetValue(mi.Name, dataType));
                    deserializeMembers.Add(mi);
                }
            }
            catch (SerializationException)
            {
                //some fiels are missing, new version, skip this fields
            }
        }
        FormatterServices.PopulateObjectMembers(m_realObject, deserializeMembers.ToArray(), data.ToArray());
    }

    public object GetRealObject( StreamingContext context )
    {
        return m_realObject;
    }
    [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
    }
}

public class McRealObjectBinder: SerializationBinder
{
    String assemVer;
    String typeVer;
    public McRealObjectBinder(String asmName, String typeName)
    {
        assemVer = asmName;
        typeVer = typeName;
    }
    public override Type BindToType( String assemblyName, String typeName ) 
    {
        Type typeToDeserialize = null;
        if ( assemblyName.Equals( assemVer ) && typeName.Equals( typeVer ) )
        {
            return typeof(McRealObjectHelper);
        }
        typeToDeserialize = Type.GetType( String.Format(  "{0}, {1}", typeName, assemblyName ) );
        return typeToDeserialize;
    }
}

然后,反序列化时:

BinaryFormatter bf = new BinaryFormatter(null, context);
bf.Binder = new McRealObjectBinder(YourType.Assembly.FullName, YourType.FullName);
bf.Deserialize(memStream);

===============>>#3 票数:4

如果只是复制几个字段的问题,我会避免所有麻烦并采取简单的路径 - 反序列化为新实例,然后将适当的字段复制到现有实例。 这将花费你几个额外的副本,但你会节省大量的时间进行调试。

===============>>#4 票数:0

这有点不寻常,但它有效:

[Serializable]
public class Pets
{
    public int Cats { get; set; }
    public int Dogs { get; set; }
}

public static class Utils
{
    public static byte[] BinarySerialize(object o)
    {
        using (var ms = new MemoryStream())
        {
            IFormatter f = new BinaryFormatter();
            f.Serialize(ms, o);
            return ms.ToArray();
        }
    }

    public static dynamic BinaryDeserialize(byte[] bytes, dynamic o)
    {
        using (var ms = new MemoryStream(bytes))
        {
            ms.Position = 0;
            IFormatter f = new BinaryFormatter();
            o = (dynamic)f.Deserialize(ms);
            return o;
        }
    }
}

对于不能通过引用传递的动态,反序列化很棘手。 最后是一个无意义的证明测试:

Pets p = new Pets() { Cats = 0, Dogs = 3 };
Console.WriteLine("{0}, {1}", p.Cats, p.Dogs);
byte[] serial = Utils.BinarySerialize(p);
p.Cats = 1;
Console.WriteLine("{0}, {1}", p.Cats, p.Dogs);
p = Utils.BinaryDeserialize(serial, p);
Console.WriteLine("{0}, {1}", p.Cats, p.Dogs);

输出如下:

0, 3
1, 3
0, 3

用文件流替换内存字符串,您将得到相同的结果。

  ask by rob translate from so

未解决问题?本站智能推荐:

1回复

将复杂xml反序列化为对象C#

我试图反序列化以下XML响应从Web服务到C#对象。 但是元素以某种方式返回null。 我在网上看了很多例子,但不确定在哪里弄错了。 我正在使用以下课程 这是我用来反序列化XML响应的代码。 我正在使用Stream Reader和Envelope类来获取字段。 Re
26回复

将JSON反序列化为C#动态对象?

有没有办法将JSON内容反序列化为C#4动态类型? 跳过创建一堆类以使用DataContractJsonSerializer会很好。
1回复

将JSON数组反序列化为C#对象

我确实需要一些反序列化JSON的帮助。 这是我的JSON: https : //min-api.cryptocompare.com/data/histoday? fsym = BTC & tsym =USD 这是我到目前为止的代码: } 我得到的错误是:Json
3回复

将XML反序列化为C#对象

我有以下xml(我无法编辑): 和以下对象,我想将其映射到: 使用以下方法: 由Deserialize(typeof(Prices), byteArrayofXMLfile); 但是,我确实收到有关xml的名称空间行的错误: 我无法弄清楚我在做什么错?
1回复

将Yaml反序列化为c#对象

我刚开始与Yaml合作,非常感谢一些意见。 我正在创建一个YAML并尝试将其取消现有的C#类。 现有的C#类: 现在我有一个Yaml, 当我尝试反序列化上面的Yaml时,我没有收到任何错误。 但是当我将我的Yaml更改为类似下面的内容时,它会知道标签Foo。 有
1回复

将SOAP消息反序列化为C#对象

因此,我尝试解析SOAP消息,并且找到了许多解决方案,但就我而言,其他解决方案给了我一个问题。 这是我要反序列化的消息: 这是我的代码: 我发现了很多类似的解决方案,但是唯一的区别是在body元素之后是需要转换为C#对象的对象。 这样的例子行之有效。 在我的情况下,
3回复

将JSON反序列化为C#对象列表

我正在尝试从Google Places API反序列化JSON。 我的自定义类设置如下,我的代码如下所示。 运行时,我的程序未引发任何错误,但我的places对象为null。
3回复

将JSON对象反序列化为C#列表

我有一些要反序列化为list <>对象的JSON。 我正在使用Newtonsoft的JsonConvert,并且已经设置了公共类来支持该列表。 这些如下。 JSON如下。 要反序列化JSON,我需要以下几行。 这就是它倒塌的地方。 JsonConvert
8回复

在C#中将XML反序列化为对象

所以我有xml看起来像这样: <todo-list> <id type="integer">#{id}</id> <name>#{name}</name> <description>#{description}
2回复

将多个json反序列化为对象c#

我试图从具有多个对象的API调用中反序列化json字符串,但没有成功。 JSON: 我创建了以下模型类: 我尝试通过将字符串反序列化为purchaseOrder来执行此操作 但没有成功。 我想也许我必须为此使用字典,但我不确定如何做到这一点。 有没有一种方法