2012-11-09 111 views
1

我试图创建一个暗示[Serializable]的属性,但我注意到这个SerializableAttribute类是封闭的。为什么C#SerializedAttribute是密封的?

在Java中有可能创建一个接口(比如,MyInterface)是从Serializable接口继承等的MyInterface所有子类也将是序列化的,甚至它的子类子会如此。

比方说,我正在创建一个ORM,我希望客户注释他们的实体类为[DatabaseEntity],但为了确保实体是可序列化的,我还需要让他们为其类别添加额外的[Serializable],相当紧凑和整洁。

我很奇怪,为什么SerializableAttribute类是sealed为什么有Inherited=false这意味着序列化类的子类不会序列化,除非它被明确指出。这些设计选择的动机是什么?

+0

你不需要'serializable'来创建一个可串行化的类。它仅由BinaryFormatter使用。其他序列化器可以愉快地序列化您的类为ex,xmlSerializer,DatacontractSerializer,DatacontractJsonSerializer,JavascriptSerializer等。 –

+0

但我希望我的类从'myObject.getType()。IsSerializable'同时返回'true'。如果您这么认为,请添加您的方法作为答案。 –

+1

你需要什么'myObject.getType()。IsSerializable'。每个类都是可序列化的(与'serializable'属性无关)。 –

回答

4

SerializableAttribute仅供BinaryFormatter使用。如果你正在编写自己的序列化程序,那么不要担心。

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

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

+0

那么C#对于[Serializable]标记类的非序列化成员是否有编译时错误机制? –

+0

字段/属性有'[NonSerializable]'。另外,一个类可以实现'ISerializable'来关闭和肮脏。再次,这只适用于BinaryFormatter。 –

-2

将[Serializable]属性放在要序列化的类的顶部。序列化是选择加入过程。您必须手动为每个想要序列化的课程做到这一点。还有一堆其他关键字。

+3

你确定你已经阅读过这个问题吗? –

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);

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

1

它建议的最佳做法所有的.Net属性应密封,according to Microsoft

.NET框架类库提供检索自定义属性的方法。默认情况下,这些方法搜索属性继承层次结构;例如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告诉,只是因为A已经被标记为[Serializable]继承这将是serialisable也并不是每一个类.NET。

  • Now class D inherits A and is serialisable,so it get its own [Serializable] attribute。

最后,在设计属性方面是延长行为(财产电网漂亮的UI编辑器等)的一个好方法。然而他们在强制执行它是可怕的。如果你需要你的客户以特定的方式实现他们的实体类,那么abstract基类或interface是更好的方法。如果你把它作为一个属性,那么你基本上是让他们知道[Serializable]是一种你可以处理的选项。

相关问题