gpt4 book ai didi

c# - 当对象是可序列化类中的字段时,转换在 ISerializable.GetObjectData 中创建的代理类型的异常

转载 作者:行者123 更新时间:2023-11-30 16:31:57 24 4
gpt4 key购买 nike

我有一个标记为 Serializable 的值对象类 (UserData),它包含另一个标记为 Serializable 并实现 ISerializable 的类 (StringType),以便它可以返回单例实例。 StringType 类本身可以很好地序列化和反序列化,但是当它用作另一个标记为可序列化的对象的属性时,我得到一个异常 truing 从帮助类反序列化转换为单例。

“Spring2.Core.Test.Serialization.StringType_DEFAULT”类型的对象无法转换为“Spring2.Core.Test.Serialization.StringType”类型。

我正在使用 BinaryFormatter 并且需要使用它以便我可以使用 SQL 服务器存储将此 UserData 对象存储在 ASP.NET session 中。

这是 StringType 类的一个非常精简的版本以及一些测试,这些测试表明序列化/反序列化对 StringType 本身有效,但在作为 UserData 上的字段时无效。

字符串类型:

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;
using System.Security.Permissions;

namespace Spring2.Core.Test.Serialization {

public enum TypeState : short {
DEFAULT,
VALID,
UNSET
}

[Serializable]
public struct StringType : ISerializable {
private string myValue;
private TypeState myState;

public static readonly StringType DEFAULT = new StringType(TypeState.DEFAULT);
public static readonly StringType UNSET = new StringType(TypeState.UNSET);

private StringType(TypeState state) {
myState = state;
myValue = "";
}

public StringType(String s) {
myValue = s;
myState = TypeState.VALID;
}

public bool IsValid {
get { return myState == TypeState.VALID; }
}

public bool IsDefault {
get { return myState == TypeState.DEFAULT; }
}

public bool IsUnset {
get { return myState == TypeState.UNSET; }
}

public override string ToString() {
return IsValid ? this.myValue : myState.ToString();
}


[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
StringType(SerializationInfo info, StreamingContext context) {
myValue = (System.String)info.GetValue("myValue", typeof(System.String));
myState = (TypeState)info.GetValue("myState", typeof(TypeState));
}

[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) {
if (this.Equals(DEFAULT)) {
info.SetType(typeof(StringType_DEFAULT));
} else if (this.Equals(UNSET)) {
info.SetType(typeof(StringType_UNSET));
} else {
info.SetType(typeof(StringType));
info.AddValue("myValue", myValue);
info.AddValue("myState", myState);
}
}
}

[Serializable]
public class StringType_DEFAULT : IObjectReference {
public object GetRealObject(StreamingContext context) {
return StringType.DEFAULT;
}
}

[Serializable]
public class StringType_UNSET : IObjectReference {
public object GetRealObject(StreamingContext context) {
return StringType.UNSET;
}
}
}

测试:

using System;

using NUnit.Framework;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

namespace Spring2.Core.Test.Serialization {

/// <summary>
/// Tests for BooleanType
/// </summary>
[TestFixture]
public class DataTypeSerializationTest {


[Test]
public void ShouldBinarySerializeStringTypeWithValue() {
BinaryFormatter binaryFmt = new BinaryFormatter();
StringType s = new StringType("foo");

FileStream fs = new FileStream("foo.dat", FileMode.OpenOrCreate);
binaryFmt.Serialize(fs, s);
fs.Close();
Console.WriteLine("Original value: {0}", s.ToString());

// Deserialize.
fs = new FileStream("foo.dat", FileMode.OpenOrCreate);
StringType s2 = (StringType)binaryFmt.Deserialize(fs);
Console.WriteLine("New value: {0}", s2.ToString());
fs.Close();

Assert.AreEqual(s.ToString(), s2.ToString());
}

[Test]
public void ShouldBinarySerializeStringTypeUnset() {
BinaryFormatter binaryFmt = new BinaryFormatter();
StringType s = StringType.UNSET;

FileStream fs = new FileStream("foo.dat", FileMode.OpenOrCreate);
binaryFmt.Serialize(fs, s);
fs.Close();
Console.WriteLine("Original value is UNSET: {0}", s.IsUnset);

// Deserialize.
fs = new FileStream("foo.dat", FileMode.OpenOrCreate);
StringType s2 = (StringType)binaryFmt.Deserialize(fs);
Console.WriteLine("new value is UNSET: {0}", s2.IsUnset);
fs.Close();

Assert.IsTrue(s2.IsUnset);
}

[Test]
public void ShouldDeserializeDataObject() {
BinaryFormatter binaryFmt = new BinaryFormatter();
UserData u = new UserData();

FileStream fs = new FileStream("foo.dat", FileMode.OpenOrCreate);
binaryFmt.Serialize(fs, u);
fs.Close();
Console.WriteLine("Original value is UNSET: {0}", u.Name.IsUnset);

// Deserialize.
fs = new FileStream("foo.dat", FileMode.OpenOrCreate);
Object o = binaryFmt.Deserialize(fs);
UserData u2 = (UserData)o;
Console.WriteLine("new value is UNSET: {0}", u2.Name.IsUnset);
fs.Close();
Assert.IsTrue(Object.Equals(u, u2));
}

}


[Serializable]
public class UserData {
private StringType name = StringType.DEFAULT;

public StringType Name {
get { return name; }
set { name = value; }
}
}

}

如有任何帮助,我们将不胜感激!

运动场

最佳答案

Cort 你应该改变你的 IObjectReference 实现来返回一个结构。第三个单元测试将失败,但它在对象相等的断言上失败,而不是抛出类型不匹配异常。

[Serializable]
public struct StringType_DEFAULT : IObjectReference {
public object GetRealObject(StreamingContext context) {
return StringType.DEFAULT;
}
}

[Serializable]
public struct StringType_UNSET : IObjectReference {
public object GetRealObject(StreamingContext context) {
return StringType.UNSET;
}
}

关于c# - 当对象是可序列化类中的字段时,转换在 ISerializable.GetObjectData 中创建的代理类型的异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4475789/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com