我试图创建一个隐含[Serializable]
的属性,但我注意到这个SerializableAttribute
类是密封的。
在Java中,可以创建一个继承自MyInterface
接口的接口(例如,Serializable
),因此MyInterface
的所有子类也可以序列化,甚至是子类-sub类就是这样。
假设我正在创建一个ORM,我希望客户将他们的实体类注释为[DatabaseEntity]
但是为了确保实体是可序列化的,我还需要让他们用额外的{{{{{{{{ 1}}看起来不那么紧凑和整洁。
我想知道为什么[Serializable]
类 SerializableAttribute
以及为什么 sealed
这意味着可序列化类的子类不会除非明确说明,否则可序列化。这些设计选择背后的动机是什么?
答案 0 :(得分:4)
SerializableAttribute仅由BinaryFormatter使用。如果您正在编写自己的序列化器,那么请不要担心。
sealed
关键字应用于属性,而不是与属性关联的类。它说SerializableAttribute不能被子类化。
BinaryFormatter
使用了选择加入模式。任何类(或子类)都必须指定它是可序列化的。这就是使用Inherited=false
的原因。
答案 1 :(得分:1)
建议最佳做法是所有 .Net属性应密封,according to Microsoft:
.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
继承B
并使用不可序列化的属性扩展它。如果.Net尝试序列化Inherited = false
,则会遇到错误。
A
告诉.Net,因为[Serializable]
已被标记为D
并非每个继承它的类都可以序列化。
现在,类A
继承了[Serializable]
并且是可序列化的,因此它获得了自己的abstract
属性。
最后,在设计属性方面,扩展行为的好方法(属性网格中的优秀UI编辑器等)。然而,他们在强制执行时非常糟糕。如果您需要客户以特定方式实现其实体类,那么interface
基类或[Serializable]
是一种更好的方法。如果你把它作为一个属性,那么你基本上让他们知道{{1}}是一个你可以处理的选项。
答案 2 :(得分: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);
反序列化过程将是读取这些值并相应地设置属性。
答案 3 :(得分:-2)
将[Serializable]属性放在要序列化的类的顶部。序列化是选择加入过程。您必须为要序列化的每个类手动执行此操作。还有许多其他关键字。