简体   繁体   English

为什么C#SerializedAttribute是密封的?

[英]Why is the C# SerializedAttribute is sealed?

I was trying to create an attribute that implies [Serializable] but I noticed that this SerializableAttribute class is sealed. 我试图创建一个暗示[Serializable]的属性,但我注意到这个SerializableAttribute类是密封的。

In Java it was possible to create an interface (say, MyInterface ) that is inherited from Serializable interface and so all the subclasses of MyInterface would also be serializable, even its sub-sub classes would be so. 在Java中,可以创建一个继承自Serializable接口的接口(例如, MyInterface ),因此MyInterface所有子类也可以序列化,甚至它的子子类也是如此。

Let's say I am creating an ORM and I want customers to annotate their entity classes as [DatabaseEntity] but in order to make sure that entities are serializable, I also need to ask them to attribute their classes with extra [Serializable] which does not look quite compact and neat. 假设我正在创建一个ORM,我希望客户将他们的实体类注释为[DatabaseEntity]但是为了确保实体是可序列化的,我还需要让他们用额外的[Serializable]来定义他们的类,这看起来并不像非常紧凑和整洁。

I am wondering why SerializableAttribute class is sealed and why has Inherited=false which implies that subclasses of serializable class will not be serializable unless it is explicitly stated. 我想知道为什么SerializableAttribute类被sealed ,为什么有Inherited=false这意味着可序列化类的子类不可序列化,除非明确说明。 What motives are behind these design choices? 这些设计选择背后的动机是什么?

The SerializableAttribute is only used by the BinaryFormatter. SerializableAttribute仅由BinaryFormatter使用。 If you are writing your own serialiser then don't worry about. 如果您正在编写自己的序列化程序,请不要担心。

The sealed keyword is applied to the attribute not the class associated with the attribute. sealed关键字应用于属性,而不是与属性关联的类。 It is saying that the SerializableAttribute cannot be subclassed. 它说SerializableAttribute不能被子类化。

The BinaryFormatter uses an opt-in model. BinaryFormatter使用选择加入模型。 Any class (or subclass) must specify that it is serializable. 任何类(或子类)都必须指定它是可序列化的。 This why the Inherited=false is used. 这就是使用Inherited=false原因。

It's suggested best practice that all .Net attributes should be sealed, according to Microsoft : 根据微软的说法,建议最佳做法是密封所有 .Net属性:

The .NET Framework class library provides methods for retrieving custom attributes. .NET Framework类库提供了检索自定义属性的方法。 By default, these methods search the attribute inheritance hierarchy; 默认情况下,这些方法搜索属性继承层次结构; for example System.Attribute.GetCustomAttribute searches for the specified attribute type, or any attribute type that extends the specified attribute type. 例如, System.Attribute.GetCustomAttribute搜索指定的属性类型或扩展指定属性类型的任何属性类型。 Sealing the attribute eliminates the search through the inheritance hierarchy, and can improve performance . 密封属性消除了通过继承层次结构的搜索,并且可以提高性能 [my emphasis] [我的重点]

So [Serializable] is sealed because it's quicker for .Net reflection to check the attributes. 因此[Serializable]是密封的,因为.Net反射检查属性的速度更快。 The cost is that you can't inherit and extend SerializableAttribute . 成本是您无法继承和扩展SerializableAttribute

You can make your own un-sealed attributes if you want (you'll get code analysis warnings though). 如果需要,您可以创建自己的未密封属性(但您会收到代码分析警告)。

This gets a little confusing with how attributes are used in inheritance for the classes that they apply to. 对于它们所适用的类的继承使用属性,这会让人感到有些困惑。 It's probably best to use an example: 最好使用一个例子:

[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;}
}

You asked why SerializableAttribute.Inherited = false and this is why: 你问为什么SerializableAttribute.Inherited = false ,这就是原因:

  • Class A is marked as [Serializable] , and it is. A被标记为[Serializable] ,它是。

  • However class B inherits A and extends it with properties that are not serialisable. 但是, B类继承A并使用不可序列化的属性扩展它。 If .Net tries to serialise B it will encounter an error. 如果.Net尝试序列化B ,则会遇到错误。

  • That Inherited = false tells .Net that just because A has been marked as [Serializable] not every class that inherits it will be serialisable too. 那个Inherited = false告诉.Net,因为A被标记为[Serializable]并不是每个继承它的类都是可序列化的。

  • Now class D inherits A and is serialisable, so it gets its own [Serializable] attribute. 现在D类继承A并且是可序列化的,因此它获得了自己的[Serializable]属性。

Finally, in terms of design attributes are a great way of extending behaviour (nice UI editors in property grids, etc). 最后,在设计属性方面是扩展行为的好方法(属性网格中的优秀UI编辑器等)。 However they are terrible at enforcing it. 然而,他们在执行它时非常糟糕。 If you need your customers to implement their entity classes in a particular way then an abstract base class or an interface is a much better way to go. 如果您需要客户以特定方式实现其实体类,那么abstract基类或interface是一种更好的方法。 If you make it an attribute then you're basically letting them know that [Serializable] is an option that you can handle either way. 如果你把它作为一个属性,那么你基本上让他们知道[Serializable]是一个你可以处理的选项。

Serialization is not a magic thing and you don't need any attribute to serialize an object. 序列化不是一件神奇的事情,您不需要任何属性来序列化对象。 It is a process of writing your class' properties and fields to a stream (and attributes are only directives to serializers about how to behave while outputting an object). 这是将类的属性和字段写入流的过程(属性只是序列化程序有关在输出对象时如何表现的指令)。

See this over-simplified serializer code which totally ignores all attributes including NonSerializable 请参阅此过度简化的序列化程序代码,该代码完全忽略包括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()));

Above code, for example, would give 例如,上面的代码会给出

IsEmpty=False
X=3
Y=5

for object obj = new Point(3,5); for object obj = new Point(3,5);

Deserialization process would be to read these values and set the properties back accordingly. 反序列化过程将是读取这些值并相应地设置属性。

Put the [Serializable] attribute on top of the class you want serialized. 将[Serializable]属性放在要序列化的类的顶部。 Serialization is opt-in process. 序列化是选择加入过程。 You have to manually do that for each class you want serialized. 您必须为要序列化的每个类手动执行此操作。 There are bunch of other keywords. 还有很多其他关键字。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM