当我想要完全按照我没有添加ISerializable时的操作时,如何在具有[Serializable]的类上实现ISerializable?

时间:2012-04-22 05:57:12

标签: c# generics serialization reflection

我有一个类,我正在序列化一些数据:

[Serializable]
public class SomeData {
    public int NumericField;
    public string StringField;
}

我有一个很方便的扩展方法:

public static string ToJson<T> (this T value) {
    // yay no compile-time checks for [Serializable]?
    if (!typeof(T).IsSerializable)
        throw new SerializationException("Object lacks [Serializable] attribute");

    var serializer = new DataContractJsonSerializer(typeof(T));

    using (var stream = new MemoryStream()) {
        using (var writer = JsonReaderWriterFactory.CreateJsonWriter(stream, Encoding.UTF8)) {
            serializer.WriteObject(writer, value);
        }

        return Encoding.UTF8.GetString(stream.ToArray());
    }
}

我真的宁愿我的班级SomeData实施ISerializable,但是当我添加它时,我被告知我需要添加一个方法:

error CS0535: 'SomeData' does not implement interface member
System.Runtime.Serialization.ISerializable.GetObjectData(
System.Runtime.Serialization.SerializationInfo, 
System.Runtime.Serialization.StreamingContext)'

问题在于我希望它能够完全它目前做什么,但也限制ToJson<T>ISerializable类,所以没有人会不小心将它传递给它这会引发一个可避免的例外。像这样:

public static string ToJson<T> (this T value) where T : ISerializable

是否有一个简明的GetObjectData实现或其他一些技巧,只会复制我在不添加ISerializable接口时会得到的确切行为?我想要一些我可以包含在我继承的类中的东西,或者简洁的东西(并且总是完全相同)我可以粘贴到所有类中我只想要[Serializable]发生的事情。通用的东西。性能不是一个大问题,但我只能使用.Net Framework 3.5。

更新:

我非常愿意在[DataContract]的位置使用[Serializable],但如果我这样做,是否有一种通用的方法可以实现ISerializable所以它只是做了什么如果我没有实施[DataContract]ISerializable会怎么做? (与您DataContract

的任何地方Serializable相同的qn

3 个答案:

答案 0 :(得分:5)

您根本不需要ISerializable,也不需要自己抛出SerializationException。如果类型不可序列化,DataContractJsonSerializer将抛出异常。 实际上有几种类型可以使用此序列化程序进行序列化:

  • Serializable属性
  • DataContract属性
  • ISerializable接口
  • 没有(适用于公共类型并序列化所有公共字段和属性)

让序列化程序执行检查将支持所有这些。

<强>更新

在评论中进行了一些讨论后,我想强调一点:

永远不会是可编译性的编译时检查(至少从C#5.0开始)。将对象标记为Serializable或甚至实现ISerializable接口并不能保证序列化程序不会在对象图中遇到非可序列化类型并在运行时抛出异常。

答案 1 :(得分:0)

  1. 正如您自己评论的那样,添加一个空白界面并将其作为约束添加到您的扩展方法中。您还可以将ISerializable添加为约束C# generics syntax for multiple type parameter constraints

  2. 另一种选择是继承实现ISerializable的基类和所需的方法

答案 2 :(得分:0)

要解决此问题,请在转换的Visual C#.NET类中实现ISerializable.GetObjectData方法。为此,请在转换后的Visual C#.NET类中添加以下代码:

void System.Runtime.Serialization.ISerializable.GetObjectData(
    System.Runtime.Serialization.SerializationInfo info,
    System.Runtime.Serialization.StreamingContext context)
{
    // Code as required
}