1

我试图创建一个暗示的属性,[Serializable]但我注意到这个SerializableAttribute类是密封的。

在 Java 中,可以创建一个从interfaceMyInterface继承的接口(比如SerializableMyInterface

假设我正在创建一个 ORM,并且我希望客户将他们的实体类注释为,[DatabaseEntity]但为了确保实体是可序列化的,我还需要要求他们为他们的类赋予额外的属性,[Serializable]这看起来不太紧凑和整洁。

我想知道为什么SerializableAttributeclass 是sealed以及为什么有Inherited=false这意味着除非明确说明,否则可序列化类的子类将不可序列化。这些设计选择背后的动机是什么?

4

4 回答 4

4

SerializableAttribute 仅由 BinaryFormatter 使用。如果您正在编写自己的序列化程序,请不要担心。

sealed关键字应用于属性而不是与属性关联的类。这是说 SerializableAttribute 不能被子类化。

使用BinaryFormatter选择加入模型。任何类(或子类)都必须指定它是可序列化的。这就是为什么Inherited=false使用 。

于 2012-11-09T22:38:01.860 回答
1

根据 Microsoft的建议,最好的做法是密封所有.Net 属性:

.NET Framework 类库提供检索自定义属性的方法。默认情况下,这些方法搜索属性继承层次结构;例如System.Attribute.GetCustomAttribute搜索指定的属性类型,或扩展指定属性类型的任何属性类型。密封属性消除了通过继承层次结构的搜索,并且可以提高性能。[我的重点]

所以[Serializable]是密封的,因为 .Net 反射检查属性更快。代价是你不能继承和扩展SerializableAttribute

如果需要,您可以创建自己的未密封属性(尽管您会收到代码分析警告)。

这有点让人困惑,属性是如何在继承中用于它们所应用的类的。最好使用一个例子:

[Serializable]
public class A
{
    public int SimpleSerialisableProperty { get; set;}
}

public class B : A
{
    public C ComplexReferenceProperty { get; set; }
}

[Serializable]
public class D : A
{
    public bool AnotherSerialisableProperty { get; set;}
}

你问为什么SerializableAttribute.Inherited = false,这就是为什么:

  • A被标记为[Serializable],它是。

  • 但是,类B继承A并使用不可序列化的属性扩展它。如果 .Net 尝试序列化B,它将遇到错误。

  • Inherited = false告诉 .Net 仅仅因为A已被标记为[Serializable]并非每个继承它的类也都是可序列化的。

  • 现在类D继承A并且是可序列化的,所以它有自己的[Serializable]属性。

最后,就设计而言,属性是扩展行为的好方法(属性网格中的漂亮 UI 编辑器等)。然而,他们在执行方面很糟糕。如果您需要您的客户以特定方式实现他们的实体类,那么abstract基类或 aninterface是一种更好的方法。如果你把它作为一个属性,那么你基本上是让他们知道这[Serializable]是一个你可以处理任何一种方式的选项。

于 2013-01-22T10:49:00.817 回答
0

序列化不是一件神奇的事情,你不需要任何属性来序列化一个对象。这是一个将你的类的属性和字段写入流的过程(属性只是序列化程序关于在输出对象时如何表现的指令)。

请参阅这个过度简化的序列化程序代码,它完全忽略了所有属性,包括NonSerializable

object obj = yourObject;

var props = obj.GetType()
               .GetProperties()
               .ToDictionary(p => p.Name, p => p.GetValue(obj, null));

string serializedText = String.Join("\n",
              props.Select(kv => kv.Key + "=" + kv.Value ?? kv.Value.ToString()));

例如,上面的代码会给

IsEmpty=False
X=3
Y=5

为了object obj = new Point(3,5);

反序列化过程将读取这些值并相应地设置属性。

于 2012-11-09T22:51:33.590 回答
-2

将 [Serializable] 属性放在要序列化的类的顶部。序列化是选择加入的过程。您必须为要序列化的每个类手动执行此操作。还有一堆其他的关键字。

于 2012-11-09T22:39:52.973 回答