[英]Why is the C# SerializedAttribute is sealed?
我試圖創建一個暗示[Serializable]
的屬性,但我注意到這個SerializableAttribute
類是密封的。
在Java中,可以創建一個繼承自Serializable
接口的接口(例如, MyInterface
),因此MyInterface
所有子類也可以序列化,甚至它的子子類也是如此。
假設我正在創建一個ORM,我希望客戶將他們的實體類注釋為[DatabaseEntity]
但是為了確保實體是可序列化的,我還需要讓他們用額外的[Serializable]
來定義他們的類,這看起來並不像非常緊湊和整潔。
我想知道為什么SerializableAttribute
類被sealed
,為什么有Inherited=false
這意味着可序列化類的子類不可序列化,除非明確說明。 這些設計選擇背后的動機是什么?
SerializableAttribute僅由BinaryFormatter使用。 如果您正在編寫自己的序列化程序,請不要擔心。
sealed
關鍵字應用於屬性,而不是與屬性關聯的類。 它說SerializableAttribute不能被子類化。
BinaryFormatter
使用選擇加入模型。 任何類(或子類)都必須指定它是可序列化的。 這就是使用Inherited=false
原因。
根據微軟的說法,建議最佳做法是密封所有 .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
基類或interface
是一種更好的方法。 如果你把它作為一個屬性,那么你基本上讓他們知道[Serializable]
是一個你可以處理的選項。
序列化不是一件神奇的事情,您不需要任何屬性來序列化對象。 這是將類的屬性和字段寫入流的過程(屬性只是序列化程序有關在輸出對象時如何表現的指令)。
請參閱此過度簡化的序列化程序代碼,該代碼完全忽略包括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
for object obj = new Point(3,5);
反序列化過程將是讀取這些值並相應地設置屬性。
將[Serializable]屬性放在要序列化的類的頂部。 序列化是選擇加入過程。 您必須為要序列化的每個類手動執行此操作。 還有很多其他關鍵字。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.